在解散另一个之后立即呈现模态视图控制器

我正在解散模态视图控制器,然后立即提出另一个,但后者从来没有发生。 代码如下:

  [self dismissModalViewControllerAnimated:YES];

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

第一个模态VC滑落,但新的picker从来没有出现。 任何想法是怎么回事?

像其他animation一样, dismissModalViewControllerAnimated在视图控制器消失之前不会阻塞。 相反,它“开始”解雇视图控制器。 您可能需要在viewDidDisappear模式控制器1中使用一个callback, viewDidDisappear类似于父视图控制器中的modalViewControllerDisappeared 。 在这种方法中,你展示的是模态控制器2.否则Robot K说的。

2012年8月更新:

iOS 5和更高版本已经引入了更安全的API来处理模块使用完成块animation进/出的地方:

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

2012年8月之前答案:

在解散模态的情况下,我遇到了类似的问题,然后快速连续地呈现模态2。 有时候,模态二会在模态被解散后显示,有时候模态二不会出现,这让我非常难过。

看起来像一个竞争条件给我…

在呈现模态2的方法的调用者上放置1+秒的延迟, showModalTwo ,使模态2每次出现在模态之后被解除:

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

这证实了一种怀疑,即解除方式之一和方式二之间存在某种竞争条件。 然而,拖延呼叫者的行为是不够的,并不能保证在其他情况下不会再出现竞赛状况。

问题

事实certificate, UIViewController有一个公共属性, modalViewController ,当presentModalViewController:animated:被调用时被设置,当dismissModalViewControllerAnimated:被调用时被拆除。 modalViewController是,它不会同步被拆除,因此可以在删除modalViewController的旧值和按照以下方式设置新值之间创build一个竞赛。

  1. 现在的模态。 myViewController.modalViewController现在指向模态
  2. closures模态一个。 后台进程拆除myViewController.modalViewController已经启动,但myViewController.modalViewController仍然指向模态
  3. 现在的模态二, myViewController.modalViewController]现在指向模态二
  4. 系统callback触发,设置myViewController.modalViewController nil ,这中断了模态二animation的过程,结果是用户从来没有看到它。

比赛从步骤2开始并在步骤4中显现。

解决scheme

我的解决scheme是在呈现模式2的方法上放置警戒条件,以确保myViewControoler.modalViewController在尝试呈现模式2之前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. } 

像魅力一样工作。 更优雅的解决scheme可能包括超时。

发布脚本

我真的不喜欢这个解决scheme的投票方面。 @Nimrod在这个问题的被接受的答案中build议,你可以安全地从模式1的viewDidDisappear:方法中启动模态2的表示。 我喜欢这个事件驱动方法的声音,但是在我的用例中做了一个完整的实现之后,我确认了在使用viewDidDisappear:内部的callback来呈现模态2时,竞态条件保持viewDidDisappear: 。 要绝对确定模态2将被呈现的唯一方法是在父视图控制器内进行轮询,直到您确定self.modalViewController nil 。 然后,只有这样才能popup模态二是“安全”的。

 [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]; 

发生了什么事情是,视图控制器一旦完成解除animation,就移除它对模态视图控制器的引用,这是在调用这个代码之后发生的,所以它不认为它有一个新的视图控制器以模态方式呈现。

我已经处理了这个是在我调用dismissModalViewController之后将didDismissModalVC伊娃设置为YES 。 然后在我的viewDidAppear:方法中,我检查了伊娃的值,然后出现了新的模态视图控制器。 (记住也设置值为NO所以我不会永远解雇模态视图控制器。

在这种情况下,我创build委托给callback父视图控制器来显示第二个模式视图控制器。

父视图控制器的定义协议:

 @protocol ParentViewControllerDelegate - (void)showModalTwo; @end 

我在父视图控制器中实现此协议以显示第二个模式视图控制器并创build委托属性@property id<ParentViewControllerDelegate> delegate; 在第一个模式视图控制器上。

从父视图控制器显示第一个模式视图控制器:

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

在第一个模式视图控制器的viewDidDisappear:方法中,只需调用delegate.showModalTwo:从父视图控制器显示第二个模式视图。

希望这个帮助。

在Swift中:

  1. 使用dismissViewControllerclosures第一个显示的视图。
  2. 使用dismissViewController的完成块来调用mainVC中的函数。 该函数应该调用第二个VC。

你的dismissViewController应该看起来像这样:

 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") }) } 

如果主要房屋出现其他VC:

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

这是我的方法,似乎在iOS 10上很好地工作。我的情况稍有不同,但应适用于大多数情况。 我提出的初始viewController作为一个popup窗口,需要一个模态viewController立即呈现。

首先,在最初的viewController的viewDidLoad直接隐藏它的视图:

  view.isHidden = true 

然后,在viewWillAppear ,呈现模态视图控制器,完成后取消animation并取消隐藏视图:

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

你可能会想用Bool来控制你的状态,这样随后的viewWillAppear调用不会重新显示模态,但是你明白了。