Представление controllerа модального вида сразу после отклонения другого

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

  [self rejectModalViewControllerAnimated: YES];

  UIImagePickerController * picker = [[UIImagePickerController alloc] init];
  picker.delegate = self;
  picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
  [self presentModalViewController: сборщик анимированных: ДА];

Первый модальный VC скользит вниз, но новый picker никогда не появляется. Любая идея о том, что происходит?

Как и другие анимированные вещи, dismissModalViewControllerAnimated не блокируется, пока controller представления не исчезнет. Вместо этого он «отменяет» увольнение controllerа вида. Возможно, вам придется использовать обратный вызов в viewDidDisappear модального controllerа 1, который вызывает в modalViewControllerDisappeared родительского представления нечто вроде modalViewControllerDisappeared . В этом методе вы представляете modal controller 2. В противном случае, что сказал Robot K.

Aug 2012 Обновление:

iOS 5 и выше ввели более безопасные API-интерфейсы для выполнения действий после того, как модалы анимировали / вне места с использованием блоков завершения:

 [self presentViewController:myModalVC animated:YES completion:^{}]; [self dismissViewControllerAnimated:YES completion:^{}]; 

До августа 2012 г. Ответ:

Я столкнулся с аналогичной проблемой при отклонении модальной формы, а затем быстро и быстро представлял модальные два. Иногда модальные два показывали после того, как модальный был уволен, а иногда модальные два вообще не появлялись, и это очень огорчило меня.

Похоже на гоночное состояние для меня …

Положив 1 + вторую задержку на вызывающего метода, который представил модальные два, showModalTwo , сделал модальные два появляющихся каждый раз после того, как модальный был уволен:

 - (void)didDismissModalOne { [self performSelector:@selector(showModalTwo:) withObject:someNumber afterDelay:1.0f]; } 

Это подтвердило подозрение, что между увольнением модального и представлением модальных двух было какое-то расы. Однако откладывание задержки на вызывающем абоненте является неэлегантным и не гарантирует, что состояние гонки не будет появляться при других обстоятельствах.

Проблема

Оказывается, что UIViewController имеет общедоступное свойство modalViewController , которое настраивается, когда presentModalViewController:animated: вызывается и dismissModalViewControllerAnimated: когда dismissModalViewControllerAnimated: Уловка заключается в том, что он не modalViewController синхронно, поэтому можно создать гонку между удалением старого значения modalViewController и настройкой нового значения следующим образом.

  1. Представьте модальный. myViewController.modalViewController теперь указывает на модальный
  2. Отбросьте модальный. Фоновый процесс для myViewController.modalViewController начался, но myViewController.modalViewController все еще указывает на модальный
  3. myViewController.modalViewController] modal два, myViewController.modalViewController] теперь указывает на модальные два
  4. Системный обратный вызов срабатывает, установив myViewController.modalViewController на myViewController.modalViewController , это прерывает процесс модального двух анимации, и результат – это тот, который никогда не видит его.

Гонка начинается на шаге 2 и проявляется на шаге 4.

Решение

Мое решение состояло в том, чтобы поставить условие охраны на метод, который представил модальный два, чтобы гарантировать, что myViewControoler.modalViewController был myViewControoler.modalViewController nil прежде чем пытаться представить модальные два.

 -(void)showModalTwo:(NSNumber *)aParameter { if (self.modalViewController) { [self performSelector:@selector(showModalTwo:) withObject:aParameter afterDelay:0.1f]; return; } // You can now present the second modal safely. } 

Работал как шарм. Более элегантное решение может включать тайм-аут.

Почтовый скрипт

Мне действительно не понравился вопрос опроса этого решения. @Nimrod предлагает в принятом ответе на этот вопрос, что вы можете безопасно инициировать презентацию модальных двух из метода viewDidDisappear: метода модального. Мне понравился звук этого подхода, основанного на событиях, но после полной реализации в моем случае использования я подтвердил, что условие гонки сохранялось при представлении модальных двух, используя обратный вызов внутри viewDidDisappear: Единственный способ быть абсолютно уверенным в том, что модальные два будут представлены, – это опрос внутри родительского controllerа представления, пока вы не будете абсолютно уверены, что self.modalViewController равен nil . Тогда и только тогда это «безопасно», чтобы поп модальные два.

 [self dismissViewControllerAnimated:YES completion:^{ //Present the new MVC }]; 

Примечание. Доступна iOS 5.0 и далее.

 [self dismissModalViewControllerAnimated:NO]; UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; [self presentModalViewController:picker animated:YES]; 

Что происходит, так это то, что controller вида удаляет ссылку на controller модального представления после завершения анимации увольнения, которая происходит после вызова этого кода, поэтому он не считает, что у него есть новый controller представления для представления модально.

Как я didDismissModalVC с этим, это установить didDismissModalVC ivar в YES после вызова функции dismissModalViewController . Затем в моем viewDidAppear: я проверяю значение ivar и присутствует, а затем новый modal view controller. (Вспоминая также, чтобы значение возвращалось к NO поэтому я не застрял на вечном увольнении controllerов модального просмотра.)

В этом случае я создаю делегат для вызова родительского controllerа представления, чтобы показать второй controller модального представления.

Протокол определения controllerа родительского представления:

 @protocol ParentViewControllerDelegate - (void)showModalTwo; @end 

Я реализую этот протокол в controllerе родительского представления, чтобы показать второй controller модального представления и создать делегатское свойство @property id delegate; на первом модульном controllerе просмотра.

Показать первый controller модального представления с родительского controllerа:

 TheFirstModalViewController *controller = ... controller.delegate = self; [self presentViewController:controller animated:YES completion:nil]; ... 

В viewDidDisappear: метод первого модального controllerа представления, просто вызовите delegate.showModalTwo: чтобы показать второй вид модальности из родительского controllerа представления.

Надеюсь, эта помощь.

В Свифт:

  1. Используйте функцию rejectViewController для отклонения первого представленного представления.
  2. Используйте блок завершения rejectViewController для вызова функции в mainVC. Эта функция должна вызывать второй VC.

Ваш rejectViewController должен выглядеть следующим образом:

 var presentingVC_Delegate: mainLists_PopoverDelegation! @IBAction fund button_Pressed (sender: AnyObject) { self.dismissViewControllerAnimated(true, completion: { finished in self.presentingVC_Delegate.presentOtherVC() print("DismissVC completion block says hello") }) } 

Где дома mainVC, что presentOtherVC:

 func presentSettingsVC () { self.performSegueWithIdentifier("present_OtherVC", sender: nil) } 

Вот мой подход, который, похоже, хорошо работает на iOS 10. Мои обстоятельства несколько отличаются, но должны работать в большинстве ситуаций. Я представляю начальный viewController как popover, который требует, чтобы модальный viewController был представлен немедленно.

Во-первых, в исходном представлении viewDidLoad просто скрывает его вид:

  view.isHidden = true 

Затем, на его viewWillAppear , представляйте модальный viewController, unanimated и не скрывайте представление при завершении:

  present(yourModalViewController, animated: false) { [unowned self] self.view.isHidden = false } 

Вероятно, вы захотите управлять своим состоянием с помощью Bool чтобы последующие вызовы viewWillAppear не viewWillAppear модальность, но вы получили эту идею.

  • Ширина пикселя текста в UILabel
  • drawRect не вызывается в моем подclassе UIImageView
  • Сохранение UIColor и загрузка из NSUserDefaults
  • Проверить версию iOS во время выполнения?
  • NSOperation на iPhone
  • NSDateFormatter dateFromString возвращает nil
  • Objective-c iPhone-процент кодирует строку?
  • Как изменить определенный цвет в изображении?
  • Как получить текущее название города?
  • Преобразование NSArray в NSDictionary
  • Метод доступа после завершения анимации UIImageView
  • Давайте будем гением компьютера.