Как выйти из этой ситуации с Уловкой 22?

У меня проблема с 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;
        }
    }

Проблема, с которой я сталкиваюсь, заключается в том, что последний оператор возврата, похоже, запускается ДО того, как завершатся блоки завершения, и я хочу, чтобы возврат был обусловлен действием пользователя, но если я помещаю возврат в Yes alertAction, тогда код ниже в методе запускается до того, как у пользователя будет возможность выбрать да / нет, поэтому я застрял. Мне нужен последний возврат, чтобы остановить выполнение кода ниже, но в то же время мне нужно дождаться завершения блока завершения? как я могу справиться с этой ситуацией, чтобы мой код под всем этим блоком кода запускался только после того, как пользователь выберет действие?

# uialertcontroller uialertaction
Источник
Codelisting
за 0 против
Лучший ответ

Каждый раз, когда вы видите API-интерфейсы, которые принимают блоки «обработчиков», лучше всего предположить, что они работают асинхронно. Это означает, что порядок операторов в исходном коде не является порядком операций.

В этом случае...

  1. presentViewController немедленно возвращается (и ваша функция возвращается сразу после этого), вызывая отображение предупреждения.
  2. Приложение продолжает вращать свой основной цикл выполнения, пока пользователь сидит и смотрит в окно предупреждения. UIKit отслеживает касания (даже если они не имеют видимого эффекта), другие элементы вашего пользовательского интерфейса могут заметно анимироваться за предупреждением или реагировать на непользовательские входы, такие как сетевая активность (которая может включать или не включать другой собственный код).
  3. Пользователь нажимает кнопку в окне предупреждения, в результате чего UIKit запускает обработчик завершения «Да» или «Нет».

Это означает, что любая логика, которую вы хотите использовать для ответа на выбор предупреждения пользователя, не может быть записана в теле метода, представляющего предупреждение. Вам нужно будет организовать запуск такого кода в результате обработки ваших предупреждений. Пример псевдокода:

- (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];
за 0 против

Вы можете попробовать прикрепить его к контроллеру корневого представления, например:

//Step 4: Present the alert to the user
UIViewController *controller = [UIApplication sharedApplication].delegate.window.rootViewController;
[controller presentViewController:userInfoCheck animated:YES completion:nil];
return;
  • 0
    Извините, как это помогает? Еще одно объяснение было бы неплохо
  • 0
    Может случиться так, что ваше « self уволено после возвращения, что разрушит все, что с ним связано. Контроллер корневого представления более постоянный.
Codelisting
Популярные категории
На заметку программисту