iOS presentedViewController&presentingViewController&dismiss的奥秘

254 阅读2分钟

众所周知iOS弹出页面通常有2种方式presentViewController或pushViewController 一个小小的present VC 当弹出多个ViewController 又想随意的关闭到指定的位置相互之间还有哪些坑点呢? 先说理念:

A->B->C->D

C.presentingViewController = B B.presentedViewController = C

1,只关闭D(C展示状态)

在D中写:

[self dismissViewControllerAnimated:YES completion:nil];

2.1,关闭C(B展示状态)

如果在C中写:

[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

如果在D中写:

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];

同理关闭到B或者C 只是presentingViewController的次数不同

2.2,关闭C(B展示状态) 如果D不归你管,你不能在D中写代码,点击D关闭的时候 D自己执行了

[self dismissViewControllerAnimated:YES completion:nil];

而你的代码只能在C中写 那么如果D关闭的时候回调给了C,C收到回调这时候执行

[self dismissViewControllerAnimated:YES completion:nil]; 是不会关闭C的

那怎么办? 执行如下代码即可

[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

结论 [self dismissViewControllerAnimated:YES completion:nil]; 只会关闭一层,而且当别人执行了 你再执行无效,但是[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];却每次都生效

疑惑: 如果self=D 那么如下代码都会只关闭D

1,[self dismissViewControllerAnimated:YES completion:nil];
2,[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

原因:

Declaration

func dismiss(animated flag: Bool, 
  completion: (() -> Void)? = nil)

Parameters

  • flag

    Pass true to animate the transition.

  • completion

    The block to execute after the view controller is dismissed. This block has no return value and takes no parameters. You may specify nil for this parameter. 

Discussion

The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.

If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.

If you want to retain a reference to the view controller's presented view controller, get the value in the presentedViewController property before calling this method.

The completion handler is called after the viewDidDisappear(_:) method is called on the presented view controller.