【问题标题】:UIAlertView showing twiceUIAlertView 显示两次
【发布时间】:2013-02-05 16:09:43
【问题描述】:

我有一个应用程序,它在某种程度上循环遍历 NSSet 的内容,并为集合中找到的每个项目显示一个 UIAlertView。当集合中只有一个项目时, UIAlertView 会正常运行。但是,如果有多个,第一个视图会闪现(通常显示集合中最后一项的内容),然后在没有任何用户干预的情况下消失。然后将显示 NSSet 中的第一项并等待响应,然后再显示 NSSet 中的下一项,依此类推。

这与此未解决问题中描述的体验相同:IPHONE: UIAlertView called twice in a custom function/IBAction

代码如下:

#import "CalcViewController.h"

@interface CalcViewController()
@property (nonatomic) int variablesCount;
@property (nonatomic, strong) NSMutableDictionary *variablesSet;
@end

@implementation CalcViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.variablesSet = [[NSMutableDictionary alloc] init];
}


- (IBAction)variablePressed:(UIButton *)sender
{
    [[self calcModel] setVariableAsOperand:sender.titleLabel.text];
    self.expressionDisplay.text = [[self calcModel] descriptionOfExpression:self.calcModel.expression];
}

- (IBAction)solveExpressionPressed:(UIButton *)sender {
    self.variablesCount = 0;
    [self.variablesSet removeAllObjects];

    NSSet *variablesCurrentlyInExpression = [[NSSet alloc] initWithSet:[CalcModel variablesInExpression:self.calcModel.expression]];
    self.variablesCount = [variablesCurrentlyInExpression count];

    if (variablesCurrentlyInExpression){
        for (NSString *item in variablesCurrentlyInExpression) {
            UIAlertView *alertDialog;
            alertDialog = [[UIAlertView alloc] initWithTitle:@"Enter value for variable"
                                                message:item
                                                delegate:self
                                                cancelButtonTitle:@"OK"
                                                otherButtonTitles:nil];

            alertDialog.alertViewStyle=UIAlertViewStylePlainTextInput;
            UITextField * alertTextField = [alertDialog textFieldAtIndex:0];
            alertTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
            [alertDialog show];
        }

    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
      if (buttonIndex == 0){
        if ([[alertView textFieldAtIndex:0] text]){         
            self.variablesSet[alertView.message] = [[alertView textFieldAtIndex:0] text];
        }
    }

    if ([self.variablesSet count] == self.variablesCount){
        NSLog(@"time to solve");
        [[self calcDisplay] setText:[NSString stringWithFormat:@"%g", [CalcModel evaluateExpression:self.calcModel.expression usingVariableValues:self.variablesSet]]];
    }
}

我检查了触发solveExpressionPressed 方法的按钮后面的IBActions,这是唯一存在的。我还在 [alertDialog show] 之前放置了一些日志记录;行,它只在 variablesCurrentlyInExpression NSSet 包含两个值时被调用两次,而 UIAlertView 出现了 3 次(闪烁一次)。

最后,我尝试了没有以下代码:

            UITextField * alertTextField = [alertDialog textFieldAtIndex:0];
            alertTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;

问题依然存在,所以我认为不是这样。

我已经被困了一段时间,还没有弄清楚(因此发帖!!),所以任何帮助都将不胜感激。

谢谢

【问题讨论】:

  • 当条件被多次满足时,你想要什么样的警报视图行为?
  • 对于表达式中的每个变量,我都会提示用户输入需要分配给该变量的值。然后,我会将这些变量:值对添加到字典中,并将它们传递给模型以求解表达式。有没有更好的方法从用户那里获取一组值(在设计时你不知道表达式中有多少变量)?我会考虑一下你的建议,然后回来看看我是多么成功。干杯

标签: objective-c cocoa-touch ios5


【解决方案1】:

尝试显示第一个 UIAlertView,然后在第一个被关闭后显示第二个。

如果应用程序或操作系统调用 [alert show] 并且 UIAlertView 已经显示,则会将原始的 alertView 放入队列并显示新的 alertView。当新的 UIAlertView 被关闭时,原来的 UIAlertView 会重新显示。

希望对你有帮助

【讨论】:

  • 您的指示很到位。我只能将一个答案标记为已接受的答案,因此我选择了 danh 来提供全面的详细信息。非常感谢您的帮助...您的描述非常清楚。
【解决方案2】:

当显示第一个警报时,使用布尔标志轻松修复,您将其设置为 YES。然后,当找到第二个匹配项并且布尔值已经是 YES 因为警报可见时,您将不会显示它。然后你可能想知道 NSSet 中匹配的确切数量。在这种情况下,您使用计数器跟踪并在匹配功能完成且计数器不为 0 后显示警报。

避免在按钮触发器的方法中显示警报。而是将每个函数拆分为不同的方法集。不仅是为了使您的函数正常工作,而且是为了以后代码的可维护性。

【讨论】:

  • 感谢您的帮助......这本来也可以,但我选择了 danh 作为接受的答案。
【解决方案3】:

要完成这个,你需要在你的类中保留一些额外的状态,像这样......

@property (strong, nonatomic) NSMutableSet *promptVariables;
@property (strong, nonatomic) NSString *promptVariable;
@property (strong, nonatomic) NSMutableDictionary *promptResults;

您可能可以通过在模型中保留一些原样(或者像您目前巧妙地在警报视图消息中隐藏一点)来减少损失,但为了清楚起见,我将使用所有新变量。

当你想发出多个提示时,像这样设置你的状态...

self.promptVariables = [[NSSet alloc] initWithSet:[CalcModel variablesInExpression:self.calcModel.expression]];
[self promptForVariables];

定义 promptForVariables 如果它没有工作要做(promptVariables 为空)则保释或删除一个并为它做警报。

- (void)promptForVariables {

    if (![self.promptVariables count]) return;
    self.promptResults = [NSMutableDictionary dictionary];

    self.promptVariable = [self.promptVariables anyObject];
    [self.promptVariables removeObject:self.promptVariable];

    // do your alert here, I won't repeat your code
}

然后,当警报完成后,按您的方式处理结果并再次调用 promptForVariables。下一次,因为你已经改变了状态,它有更少的工作要做。

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
      if (buttonIndex == 0){
        if ([[alertView textFieldAtIndex:0] text]){         
            [self.promptResults setValue:[[alertView textFieldAtIndex:0] text] forKey:self.promptVariable];
        }
        [self performSelector:@selector(promptForVariables) withObject:nil afterDelay:0.0];
    }
}

完成后,promptResults 将包含变量名称作为键和用户输入作为值。

【讨论】:

  • 优秀的东西......完美运行(除了必须在最终代码部分的“[self promptResults”周围添加点或方括号。感谢您的帮助
  • 很高兴听到。编辑以修复语法。此外,添加了一项更改 - 在随后的 promptForVariables 调用中执行选择器会将控制权返回给事件循环,以便用户界面可以更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多