开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
present视图生命周期
前几天遇到一个问题,是关于摄像头的,事实情况是这样的:项目的首页Home是一个摄像头预览页面,可以看到自己,在 Home页面present一个页面去录制视频,需要把摄像头抢走,在dismiss之后,Home页面在viewWillAppear重新拿回摄像头,问题来了
1、present的页面,在dismiss之后,Home页面并没有走viewWillAppear,为什么?
2、解决问题1之后,拿到摄像头了,Home的摄像头确是卡住的,发现在deinit调用了stopCamera,
问题2让我突然想起来了当年的一个面试题,present的生命周期,今天围绕两个问题,做一下记录。
present生命周期
两个问题,我们在查看present生命周期的时候,一次性就可以了解了。
问题1和modalPresentationStyle有关,我们做一个实现,现在有AVC和BVC,AVC present到 BVC,BVC dismiss到AVC,在不同参数下是不是有什么变化?
| 参数 | present | dismiss | |
|---|---|---|---|
| fullScreen | B viewDidLoad A viewWillDisappear B viewWillAppear B viewDidAppear A viewDidDisappear | B viewWillDisappear A viewWillAppear A viewDidAppear B viewDidDisappear B deinit | 使用这种模式时,presented VC的宽高与屏幕相同,并且UIKit会直接使用rootViewController做为presentation context,在此次presentation完成之后,UIKit会将presentation context及其子VC都移出UI栈,这时候观察VC的层级关系,会发现UIWindow下只有presented VC. |
| pageSheet | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deinit | presented VC的宽高均小于屏幕尺寸,其余部分用透明背景填充。对于紧凑型设备的水平方向及所有设备的竖直方向 |
| formSheet | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deinit | presented VC的宽高均小于屏幕尺寸,其余部分用透明背景填充。对于紧凑型设备的水平方向及所有设备的竖直方向,其显示效果与pageSheet相同 |
| currentContext | B viewDidLoad A viewWillDisappear B viewWillAppear B viewDidAppear A viewDidDisappear | B viewWillDisappear A viewWillAppear A viewDidAppear B viewDidDisappear B deinit | presented VC的宽高取决于presentation context的宽高,并且UIKit会寻找属性definesPresentationContext为YES的VC作为presentation context,具体的寻找方式会在下文中给出 。当此次presentation完成之后,presentation context及其子VC都将被暂时移出当前的UI栈。 |
| custom | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deinit | 自定义模式,需要实现UIViewControllerTransitioningDelegate的相关方法,并将presented VC的transitioningDelegate 设置为实现了UIViewControllerTransitioningDelegate协议的对象。 |
| overFullScreen | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deinit | 与UIModalPresentationFullScreen的唯一区别在于,UIWindow下除了presented VC,还有其他正常的VC层级关系。也就是说该模式下,UIKit以rootViewController为presentation context,但presentation完成之后不会讲rootViewController移出当前的UI栈。 |
| overCurrentContext | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deinit | overCurrentContext:(新)这个模式也能达到overFullScreen的效果,不同的是它会把跟控制器(tabbar)覆盖到presented VC上面(读了API还是搞不清是啥意思。。。) |
| popover | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deini | popover:一种类似于Mac上全局字典的弹出方式,带有一个箭头,在iphone上显示的是全屏效果,只有在大屏幕上才显示popover效果。 |
最终总结
| 参数 | present | dismiss |
|---|---|---|
| fullScreen currentContext | B viewDidLoad A viewWillDisappear B viewWillAppear B viewDidAppear A viewDidDisappear | B viewWillDisappear A viewWillAppear A viewDidAppear B viewDidDisappear B deinit |
| pageSheet formSheet custom overFullScreen overCurrentContext popover | B viewDidLoad B viewWillAppear B viewDidAppear | B viewWillDisappear B viewDidDisappear B deini |
pushViewController生命周期
| push | pop |
|---|---|
| B viewDidLoad A viewWillDisappear B viewWillAppear A viewDidDisappear B viewDidAppear | B viewWillDisappear A viewWillAppear B viewDidDisappear A viewDidAppear B deinit |
结论
看到上诉的生命周期其实就能了解到为什么会出现上面的2个现象。写代码一定要注意,都是小细节。