在解散另一个之后立即呈现模态视图控制器
我正在解散模态视图控制器,然后立即提出另一个,但后者从来没有发生。 代码如下:
[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一个竞赛。
- 现在的模态。
myViewController.modalViewController
现在指向模态 - closures模态一个。 后台进程拆除
myViewController.modalViewController
已经启动,但myViewController.modalViewController
仍然指向模态 - 现在的模态二,
myViewController.modalViewController]
现在指向模态二 - 系统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中:
- 使用dismissViewControllerclosures第一个显示的视图。
- 使用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
调用不会重新显示模态,但是你明白了。