Представление контроллера вида модально из делегата листа действий в 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 58

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, и я решил свою проблему, выбрав "текущий контекст" для презентации вариант

Я надеюсь, это будет полезно для кого-то другого... вот скриншот о опции

enter image description here

у меня была такая же проблема. Я создал отдельное окно для предупреждений и таблиц действий в моем 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.