问题
- A present B,A,B的
viewWillAppear
、viewDidAppear
、viewWillDisappear
和viewDidDisappear
调用顺序是怎样的? - A页面的
viewWillDisappear
和viewDidDisappear
在什么情况会调用,什么情况不会调用,为什么? - 在自定义了转场之后(modalPresentationStyle设置为custom),怎么让A页面的
viewWillDisappear
和viewDidDisappear
调用?
项目中之前modal实现的一个转场场景,忽然需要加一个转场动画,心想就是半个小时搞定的事情,无非就是实现两个delegate,UIViewControllerTransitioningDelegate
和UIViewControllerAnimatedTransitioning
,然后自定义一个动画,结果一做,差点陷入坑里
问题1
大概场景是这样的: presentingViewController
(A页面)上面有个播放器,然后present出presentedViewController
(B页面)全屏播放
之前由于modalPresentationStyle
设置的是UIModalPresentationStyle.fullScreen
,
那么在转场过程中,两个VC的生命周期大概是这样的
历史逻辑在presentingViewController
(A页面)Disappear时需要做一些操作
问题2
加入自定义转场,modalPresentationStyle
必须设置为UIModalPresentationStyle.custom
modalPresentationStyle
设置为UIModalPresentationStyle.custom
,那么presentingViewController
的viewWillDisappear
和viewDidDisappear
就不会调用了
至于这里为什么不调用,其实我是知道原因的
先说在UIModalPresentationStyle.fullScreen
下为什么会调用viewWillDisappear
和viewDidDisappear
When presenting a view controller using the UIModalPresentationFullScreen style, UIKit normally removes the views of the underlying view controller after the transition animations finish. You can prevent the removal of those views by specifying the UIModalPresentationOverFullScreen style instead. You might use that style when the presented view controller has transparent areas that let underlying content show through.
大意:
当使用UIModalPresentationFullScreen
样式presenting一个view controller时,UIKit 通常会在过渡动画完成后移除底层视图控制器的视图,你可以通过指定 UIModalPresentationOverFullScreen
样式来防止删除这些视图,当呈现的view controller想让底层内容显示在透明区域时,您可以使用该样式,就是present一个B页面后,下面的presentingViewController
(A页面)还在
那么在UIModalPresentationStyle.fullScreen
下为什么会调用viewWillDisappear
和viewDidDisappear
就很好解释了,因为在转场时,他会移除下面的viewController
modalPresentationStyle
为UIModalPresentationOverFullScreen
的视图结构
modalPresentationStyle
为UIModalPresentationOverCustom
的视图结构
可以看到在UIModalPresentationOverCustom
模式下,presentingViewController
(A页面)还在,没有被移除,这也就解释了,为什么viewWillDisappear
和viewDidDisappear
不调用
再看viewWillDisappear和viewDidDisappear的文档,在什么时候,这两个方法会调用
viewwilldisappear
This method is called in response to a view being removed from a view hierarchy. This method is called before the view is actually removed and before any animations are configured
大意:
调用此方法是为了响应从视图层次结构中删除的视图。在实际删除视图之前和配置任何动画之前调用此方法
viewDidDisappear
Notifies the view controller that its view was removed from a view hierarchy
大意
通知视图控制器它的视图已从视图层次结构中删除
那么到了这里,我们可以知道,在modal切换的场景中,presentingViewController
(A页面)的viewwilldisappear
和viewDidDisappear
调用,是和modalPresentationStyle
有关的
那么modalPresentationStyle
作为一个枚举属性,他的每个变量,具体作用又是什么?
modalPresentationStyle
定义如下
public enum UIModalPresentationStyle : Int {
case fullScreen = 0
@available(iOS 3.2, *)
case pageSheet = 1
@available(iOS 3.2, *)
case formSheet = 2
@available(iOS 3.2, *)
case currentContext = 3
@available(iOS 7.0, *)
case custom = 4
@available(iOS 8.0, *)
case overFullScreen = 5
@available(iOS 8.0, *)
case overCurrentContext = 6
@available(iOS 8.0, *)
case popover = 7
@available(iOS 7.0, *)
case none = -1
@available(iOS 13.0, *)
case automatic = -2
}
以下说明摘至详解iOS的presentViewController
UIModalPresentation.fullScreen
UIKit默认的presentation style。 使用这种模式时,presented VC的宽高与屏幕相同,并且UIKit会直接使用rootViewController做为presentation context,在此次presentation完成之后,UIKit会将presentation context及其子VC都移出UI栈,这时候观察VC的层级关系,会发现UIWindow下只有presented VC.
-
UIModalPresentation.pageSheet
在常规型设备(大屏手机,例如plus系列以及iPad系列)的水平方向,presented VC的高为当前屏幕的高度,宽为该设备竖直方向屏幕的宽度,其余部分用透明背景做填充。对于紧凑型设备(小屏手机)的水平方向及所有设备的竖直方向,其显示效果与UIModalPresentationFullScreen相同。 -
UIModalPresentation.formSheet
在常规型设备的水平方向,presented VC的宽高均小于屏幕尺寸,其余部分用透明背景填充。对于紧凑型设备的水平方向及所有设备的竖直方向,其显示效果与UIModalPresentationFullScreen相同 -
UIModalPresentation.currentContext
使用这种方式present VC时,presented VC的宽高取决于presentation context的宽高,并且UIKit会寻找属性definesPresentationContext为YES的VC作为presentation context,具体的寻找方式 。当此次presentation完成之后,presentation context及其子VC都将被暂时移出当前的UI栈。 -
UIModalPresentation.custom
自定义模式,需要实现UIViewControllerTransitioningDelegate的相关方法,并将presented VC的transitioningDelegate 设置为实现了UIViewControllerTransitioningDelegate协议的对象。 -
UIModalPresentation.overFullScreen
与UIModalPresentationFullScreen的唯一区别在于,UIWindow下除了presented VC,还有其他正常的VC层级关系。也就是说该模式下,UIKit以rootViewController为presentation context,但presentation完成之后不会将rootViewController移出当前的UI栈。 -
UIModalPresentation.overCurrentContext
寻找presentation context的方式与UIModalPresentationCurrentContext相同,所不同的是presentation完成之后,不会将context及其子VC移出当前UI栈。但是,这种方式只适用于transition style为UIModalTransitionStyleCoverVertical的情况(UIKit默认就是这种transition style)。其他transition style下使用这种方式将会触发异常。 -
UIModalPresentation.popover
主要配合UIPopoverPresentationController
使用,做一个气泡弹窗视图 -
UIModalPresentation.automatic
iOS 13出来的新样式,有层次结构那种
到这里我们对对modalPresentationStyle
有了一个深入的了解,接着看问题3
问题3
从之前的分析,我门知道,presentingViewController
(A页面)的viewwilldisappear
和viewDidDisappear
不调用,是和modalPresentationStyle
为UIModalPresentation.custom
有关
那么现在我们需要presentingViewController
(A页面)从试图层级上移除,来触发viewwilldisappear
和viewDidDisappear
的调用
通过各种研究官方文档和stackoverflow
最终找到了答案
完美解决了以上所有问题
总结
- A present B,A,B的
viewWillAppear
、viewDidAppear
、viewWillDisappear
和viewDidDisappear
调用顺序是怎样的?
🍀🍀🍀 开始显示 PresentedVC 🍀🍀🍀
PresentingVC viewWillDisappear(_:)
PresentedVC viewWillAppear(_:)
PresentedVC viewDidAppear(_:)
PresentingVC viewDidDisappear(_:)
- A页面的
viewWillDisappear
和viewDidDisappear
在什么情况会调用,什么情况不会调用,为什么?
根据
modalPresentationStyle
的类型决定,如果不需要从视图层级上移除的就不会掉用,反之
- 在自定义了转场之后(modalPresentationStyle设置为custom),怎么让A页面的
viewWillDisappear
和viewDidDisappear
调用?
自定义
UIPresentationController
,并将shouldRemovePresentersView
返回true
本文测试Demo
今天的文章UIModalPresentationStyleCustom不调用viewWillDisappear问题分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14571.html