如何摆脱这种Catch 22的局面?

时间:2017-11-07 04:42:49

标签: objective-c uialertcontroller uialertaction

我有一个Catch 22问题,我无法摆脱,我正在使用UIAlertCOntroller向用户显示信息,并根据我需要采取一些行动的答案

if([NWTillHelper finishTransactionWithoutEmail] != 1) {
        if([NWTillHelper getCrmId] == nil) {
            //Step 1: Create a UIAlertController
            UIAlertController *userInfoCheck = [UIAlertController alertControllerWithTitle:@"No Customer Email!"
                                                                                   message: @"Do you want to proceed without customer email? No receipt will be sent out in this case!"
                                                                            preferredStyle:UIAlertControllerStyleAlert];

            //Step 2: Create a UIAlertAction that can be added to the alert
            UIAlertAction *Yes = [UIAlertAction
                                  actionWithTitle:@"Yes"
                                  style:UIAlertActionStyleDefault
                                  handler:^(UIAlertAction * action)
                                  {
                                      NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
                                      [tillUserDefaults setInteger:1 forKey:@"finishTransactionWithoutEmail"];
                                      [tillUserDefaults synchronize];
                                      [userInfoCheck dismissViewControllerAnimated:YES completion:nil];
                                  }];

            UIAlertAction *No = [UIAlertAction
                                 actionWithTitle:@"No"
                                 style:UIAlertActionStyleDefault
                                 handler:^(UIAlertAction * action)
                                 {
                                     [userInfoCheck dismissViewControllerAnimated:YES completion:nil];
                                 }];

            //Step 3: Add the UIAlertAction ok that we just created to our AlertController
            [userInfoCheck addAction: Yes];
            [userInfoCheck addAction: No];

            //Step 4: Present the alert to the user
            [self presentViewController:userInfoCheck animated:YES completion:nil];
            return;
        }
    }

我遇到的问题是,最后一个return语句似乎是在完成块完成之前运行的,我希望返回条件是用户操作,但如果我将返回值设置为Yes alertAction则代码如下在方法运行之前,用户有机会选择是/否所以我卡住了我需要最后一次返回来停止下面的代码运行但同时我需要等待完成块完成?如何处理这种情况,以便我的代码在整个代码块下面只在用户选择操作后运行?

2 个答案:

答案 0 :(得分:0)

您可以尝试将其附加到根视图控制器,例如:

//Step 4: Present the alert to the user
UIViewController *controller = [UIApplication sharedApplication].delegate.window.rootViewController;
[controller presentViewController:userInfoCheck animated:YES completion:nil];
return;

答案 1 :(得分:0)

Any time you see APIs that accept "handler" blocks, it's best to assume they run asynchronously. That means that the order of statements in your source code is not the order of operations.

In this case...

  1. presentViewController returns immediately (and your function returns immediately thereafter), causing the alert to show.
  2. The app continues to spin its main run loop while the user is sitting there looking at the alert box. UIKit tracks touches (even if they have no visible effect), other elements of your UI might be animating visibly behind the alert or reacting to non-user inputs like network activity (which may or may not involve other code of your own).
  3. The user taps a button in the alert box, causing UIKit to run either your Yes or No completion handler.

This means that whatever logic you want to use for responding to the user's alert choice cannot be written in the method body that presents the alert. You'll need to arrange for such code to run as a result of your alert action handlers. A pseudocode-ish example:

- (void)handleEmailChoice:(BOOL)proceedWithoutEmail {
    // do whatever depends on user choice
}

// elsewhere
UIAlertController *userInfoCheck = [UIAlertController alertControllerWithTitle:/*...*/];
UIAlertAction *yes = [UIAlertAction actionWithTitle:@"Yes"
                              style:UIAlertActionStyleDefault
                              handler:^(UIAlertAction * action)
                              {
                                 // set defaults, dismiss alert, then:
                                 [self handleEmailChoice:YES];
                              }];

UIAlertAction *no = [UIAlertAction actionWithTitle:@"No"
                             style:UIAlertActionStyleDefault
                             handler:^(UIAlertAction * action)
                             {
                                 // dismiss alert, then:
                                 [self handleEmailChoice:NO];
                             }];

[userInfoCheck addAction: yes];
[userInfoCheck addAction: no];
[self presentViewController:userInfoCheck animated:YES completion:nil];