0

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

这与这个未解决的问题中描述的体验相同:IPHONE: UIAlertView 在自定义函数/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;

并且问题仍然存在,所以我不认为是那样。

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

谢谢

4

3 回答 3

1

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

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

希望这可以帮助

于 2013-02-05T16:42:45.417 回答
1

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

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

于 2013-02-05T16:51:29.750 回答
0

为了完成这件事,你需要在课堂上保留一些额外的状态,就像这样......

@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];

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

- (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 将包含变量名称作为键和用户输入作为值。

于 2013-02-05T17:00:23.433 回答