ViewController视图生命周期

689 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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,在不同参数下是不是有什么变化?

参数presentdismiss
fullScreenB viewDidLoad A viewWillDisappear B viewWillAppear B viewDidAppear A viewDidDisappearB 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.
pageSheetB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deinitpresented VC的宽高均小于屏幕尺寸,其余部分用透明背景填充。对于紧凑型设备的水平方向及所有设备的竖直方向
formSheetB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deinitpresented VC的宽高均小于屏幕尺寸,其余部分用透明背景填充。对于紧凑型设备的水平方向及所有设备的竖直方向,其显示效果与pageSheet相同
currentContextB viewDidLoad A viewWillDisappear B viewWillAppear B viewDidAppear A viewDidDisappearB viewWillDisappear A viewWillAppear A viewDidAppear B viewDidDisappear B deinitpresented VC的宽高取决于presentation context的宽高,并且UIKit会寻找属性definesPresentationContext为YES的VC作为presentation context,具体的寻找方式会在下文中给出 。当此次presentation完成之后,presentation context及其子VC都将被暂时移出当前的UI栈。
customB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deinit自定义模式,需要实现UIViewControllerTransitioningDelegate的相关方法,并将presented VC的transitioningDelegate 设置为实现了UIViewControllerTransitioningDelegate协议的对象。
overFullScreenB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deinit与UIModalPresentationFullScreen的唯一区别在于,UIWindow下除了presented VC,还有其他正常的VC层级关系。也就是说该模式下,UIKit以rootViewController为presentation context,但presentation完成之后不会讲rootViewController移出当前的UI栈。
overCurrentContextB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deinitoverCurrentContext:(新)这个模式也能达到overFullScreen的效果,不同的是它会把跟控制器(tabbar)覆盖到presented VC上面(读了API还是搞不清是啥意思。。。)
popoverB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deinipopover:一种类似于Mac上全局字典的弹出方式,带有一个箭头,在iphone上显示的是全屏效果,只有在大屏幕上才显示popover效果。

最终总结

参数presentdismiss
fullScreen currentContextB viewDidLoad A viewWillDisappear B viewWillAppear B viewDidAppear A viewDidDisappearB viewWillDisappear A viewWillAppear A viewDidAppear B viewDidDisappear B deinit
pageSheet formSheet custom overFullScreen overCurrentContext popoverB viewDidLoad B viewWillAppear B viewDidAppearB viewWillDisappear B viewDidDisappear B deini

pushViewController生命周期

pushpop
B viewDidLoad A viewWillDisappear B viewWillAppear A viewDidDisappear B viewDidAppearB viewWillDisappear A viewWillAppear B viewDidDisappear A viewDidAppear B deinit

结论

看到上诉的生命周期其实就能了解到为什么会出现上面的2个现象。写代码一定要注意,都是小细节。

相关链接

www.jianshu.com/p/af990d838…