Как выйти из этой ситуации с Catch 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;
}
}
Проблема, с которой я сталкиваюсь, заключается в том, что последний оператор return кажется выполненным ДО завершения блоков завершения, и я хочу, чтобы возврат был условным для действия пользователя, но если я добавлю возвращение в Yes alertAction, тогда приведенный ниже код в методе запускается до того, как у пользователя есть возможность выбрать да / нет, поэтому я застрял, мне нужно последнее возвращение, чтобы остановить код ниже, чтобы быть запущенным, но в то же время мне нужно дождаться завершения блока завершения? Как я могу справиться с этой ситуацией, чтобы мой код под всем этим блоком кода запускался только после того, как пользователь выбрал действие?
2 ответа
Каждый раз, когда вы видите API, которые принимают блоки "обработчики", лучше предположить, что они работают асинхронно. Это означает, что порядок операторов в вашем исходном коде не является порядком операций.
В этом случае...
presentViewController
немедленно возвращается (и ваша функция возвращается сразу после этого), вызывая показ предупреждения.- Приложение продолжает вращать свой основной цикл выполнения, пока пользователь сидит и смотрит на окно предупреждения. UIKit отслеживает прикосновения (даже если они не имеют видимого эффекта), другие элементы вашего пользовательского интерфейса могут заметно анимировать за оповещением или реагировать на не-пользовательские входные данные, такие как сетевая активность (которая может включать или не включать другой ваш собственный код).
- Пользователь нажимает кнопку в окне предупреждения, в результате чего 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];
Вы можете попробовать подключить его к контроллеру корневого представления, например:
//Step 4: Present the alert to the user
UIViewController *controller = [UIApplication sharedApplication].delegate.window.rootViewController;
[controller presentViewController:userInfoCheck animated:YES completion:nil];
return;