Представление контроллера вида модально из делегата листа действий в iOS8 - iOS11
поэтому я заметил, что в iOS8 beta 3 (обновление: все еще происходит в iOS 11.2) на iPad, при попытке представить контроллер представления из метода делегата a UIActionSheet
," ничего " не происходит, и на консоль отладки выводится сообщение журнала, в котором говорится, что презентация была предпринята при переходе на контроллер предупреждений:
Warning: Attempt to present <UIViewController: 0x...> on <ViewController: 0x...> which is already presenting <UIAlertController: 0x...>
9 ответов:
обновление: начиная с iOS 9 SDK,
UIActionSheet
является устаревшим, поэтому не ожидайте исправления этой проблемы. Лучше всего начать использоватьUIAlertController
когда это возможно.
проблема, похоже, исходит от переключения Apple на использование
UIAlertController
внутренне для реализации функциональности представлений предупреждений и листов действий. Проблема видна в основном на iPad и листах действий, потому что на iPad листы действий представлены как всплывающее окно в указанном представлении, и то, что делает Apple путешествуйте по цепочке ответчика, пока он не найдет контроллер вида и не вызоветpresentViewController:animated:completion:
внутренниеUIAlertController
. Проблема менее очевидна на iPhone и с предупреждающими видами, потому что там Apple фактически создает отдельное окно, пустой контроллер вида и представляет внутреннийUIAlertController
кроме того, так что это, кажется, не мешает другой презентации.Я открыл отчет об ошибке для этого вопроса: rdar://17742017. Пожалуйста, продублируйте его и дайте Apple знать, что это проблема.
в качестве обходного пути я рекомендую отложить презентацию до следующего runloop, используя следующий метод:
dispatch_async(dispatch_get_main_queue(), ^ { [self presentViewController:vc animated:YES completion:nil]; });
вы можете попробовать сделать свою работу (представление контроллера вида) в
- (void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {}
вместо
- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {}
как сказал @LeoNatan, "проблема, похоже, исходит от переключения Apple на использование UIAlertController внутри для реализации функциональности представлений предупреждений и листов действий". Поэтому вы должны дождаться, когда лист действий будет отклонен, а затем представить контроллер вида, который вы хотите.
решение @ LeoNatan просто блокирует пользовательский интерфейс в главном потоке, поэтому он также будет убедитесь, что контроллер вида будет представлен после того, как лист действий был отклонен.
к сожалению, этот код не работает для меня, я думаю, потому что моя проблема не вызывала метод presentController напрямую, а в методе prepareForSegue, поэтому используя
[segue destinationViewController]
Я заметил, что если segue "push" вид все работает правильно, но если это "модальный", только в ipad, я получил эту ошибку.
затем я нашел новую опцию в раскадровке на панели segue, и я решил свою проблему, выбрав "текущий контекст" для презентации вариант
Я надеюсь, это будет полезно для кого-то другого... вот скриншот о опции
у меня была такая же проблема. Я создал отдельное окно для предупреждений и таблиц действий в моем appdelegate и представил предупреждения на нем. Это сработало для меня!
self.alertWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.alertWindow.backgroundColor = [UIColor clearColor]; UIViewController *dummy = [[UIViewController alloc] init]; [self.alertWindow setRootViewController:dummy];
Вы можете представить как :
[[myAppDelegate appDelegate].alertWindow makeKeyAndVisible]; [[myAppDelegate appDelegate].alertWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
я исправил это в Swift 3 со следующим кодом
DispatchQueue.main.async { self.present(alertController, animated: true, completion: nil) }
выдает
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
on
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
прежде чем пытаться представить другой модальный работал для меня.
использовать
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
вместо
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
вид действия представлен выше текущего VC, так что это то, что вызывает предупреждение/ошибку. когда diddismiss называется, вид действия уже отклонен, так что никаких проблем вообще :))
попробовать
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ // action sheet presentation // or modal view controller presentation // or alert view presentation }];
В iOS 8 Apple использует UIAlertController внутренне для реализации функциональности представлений предупреждений и листов действий. Поэтому, когда вы хотите показать UIViewController модально после отображения UIActionSheet или UIAlertView в методе делегата, например
(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
и
(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
вы должны сначала уволить UIAlertController следующим образом:
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) { UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; [vc dismissViewControllerAnimated:NO completion:^{ }]; }
Теперь вы можете представить модальный UIViewController в iOS 8.