总结ViewController Lifecycle

ViewController Lifecycle
- VC被实例化(通常从storyboard)
- awakFromNib(只有从storyboard中实例化的VC会调用)
- segue点击事件的准备
- outlets被设置
- viewDidLoad
- viewWillAppear & viewDIdAppear
- viewWillDisappear & viewDidDisappear
-
【注意】:Lifecycle中的任意时间,任意时间viewWillLayoutSubviews() && viewDidLayoutSubviews() 都可能发生,同样didReceiveMemoryWarning也可能发生。
1. viewDIdLoad

viewDIdLoad
- 做一些基础的MVC设置,只会调用一次
- viewDIdLoad方法在Outlets被设置之前,这是一个很好的时机去从Model层更新View
-
【注意】:不要在viewDIdLoad里做和尺寸有关的设置,因为你的bounds此时还没有被设置,还没有确定适配什么设备尺寸
2. viewWillAppear

image.png
- 在view即将出现在屏幕上时调用,在屏幕离开又再次进入时,会多次调用
- 在这里可以更新动态的数据,
3. viewDIdAppear

viewDIdAppear.png
- 此时界面已经显示在屏幕上,不适合做界面的更新,适合开始动画,开启计时器,开启GPS,开始观察、监听某些属性(GPS的位置,手机陀螺仪的位置),等等
- 因为viewDIdLoad、viewWillAppear并不能保证view出现在屏幕上,所以viewDIdAppear适合做一些需要昂贵开销(时间,内存)的工作,比如从网络上下载一个巨大的图片资源
-
【注意】:iOS程序永远要保证用户能够与手机交互,能触碰到屏幕上的东西,如果开销巨大的工作未完成,需要有动画,旋转加载器,默认图片(文字)等,来使得界面能正常工作,不能让程序被冻结,解决办法就是将这些开销很大的工作放在主线程之外。
4. viewWillDisappear

viewWillDisappear.png
- 在这里撤销一些事情,比如停止计时器,停止动画, 停止GPS
5. viewDidDisappear

viewDidDisappear.png
6. viewWillLayoutSubviews() && viewDidLayoutSubviews()

viewWillLayoutSubviews() && viewDidLayoutSubviews() .png
- 当view的尺寸发生改变,有subviews的增加或者删除,或者需要重新布局时,会调用这个方法
- 如果用AutoLayout设置的view(在storyboard中设置了边距,长款,中心对称,长宽比等等数据),不需要调用这个方法
- 这两个方法会被频繁的调用,不要在这里调用一些复杂的方法,因为频繁得调用会使得开销增大
7 didReceiveMemoryWarning

image.png
- 当内存不足时,你可以在这里从堆中清理一些大内存的视频图片,或者清理一些目前不要的东西,并在之后需要时重新获得(比如从网络上重新下载数据)
- 当不断发出警告时,此程序有可能被iOS杀死
8. awakFromNib

awakFromNib
- awakFromNib事实上并不是生命周期的一部分
- 这个方法被调用的非常早,比outlets的设置和准备好segue更早
- 在某些代码需要很早就被执行时,在这个方法里完成,但是最好不要用
设置自定义开始ViewController的步骤
- 删除storyboard中的默认控制器和原始ViewController
- 自定义创建ViewController(假设叫imageViewController), 并在Main.storyboard中拖出一个新的ViewController,将脱出的ViewController的类型设置为imageViewController
- 将这个imageViewController设置为初始的ViewController(右边initial ViewController 打勾)
设置自定义开始ViewController的步骤
- 删除storyboard中的默认控制器和原始ViewController
- 自定义创建ViewController(假设叫imageViewController), 并在Main.storyboard中拖出一个新的ViewController,将脱出的ViewController的类型设置为imageViewController
- 将这个imageViewController设置为初始的ViewController(右边initial ViewController 打勾)
如何确保view正在屏幕上?
- if view.window != nil 来判断self是否显示在屏幕上,当屏幕上即将出现self,再在viewDidAppear里操作
do catch
do {
let urlContents = try Data(contentsOf: url)
// 利用try做网络请求,可能返回失败(网络链接不好,断网的诸多原因)
} else let error {
// 这里来捕捉失败
}
------------------------------------------------------------------------
let urlContents = try? Data(contentsOf: url)
//try? 代表尝试这个操作,如果返回失败,只需要返回nil
//所以这里的urlContents的类型是,Data?
UIImage的两种初始化方式
UIIamge(named: " xxx ")// 用类型为String的名字,初始化一个UIImage
UIIamge(data: Data )// 用类型为Data的数据,初始化一个UIImage
-
Bundle.main.url(forResource:"imageName" , withExtension:"jpg")
,这个函数可以获取本地的资源(返回一个本地url),在将资源拖进项目后,需要把Target Membership勾选上(点击被拖进来的资源,在右边的inspector里,原因:这样做可以保证在设备安装这个app时,资源在app里面)
UIScrollView
- scrollView属性contentSize规定了scrollView可以滑动的大小
- scrollView.minimumZoomScale 设置最小缩放大小
- scrollView.maximumZoomScale 设置最大缩放大小
- scrollView.delegate 设置代理,可以实现一些代理方法(所有方法都是Objective-C可选方法)
- scrollView代理方法:
func viewForZooming(in scrollView:UIScrollVIew)-> UIView? {
// 返回你需要在scrollView中缩放的View
return imageView
}
sizeToFit()
-
imageView.sizeToFit()
,可以让imageView的大小自适应图片本身的大小
如何利用computed var 去优化代码
- 待优化的问题:假设imageView是一个UIImage,它每次被重新赋值后,都需要被重新修改frame,而且其父组件scrollView的属性contentSize也需要随之更改。
- 解决方案:使用一个计算属性image来封装imageView,在每次要获得image的地方,返回imageView的内容,而每次image被设置后,它会将被设置的UIImage值传给真正起作用的imageView,并且将sizeToFit()和scrollView.contentSize封装进去
- 达到的效果:起到了优化代码的作用,以后只需要给image赋值,就可以完成对imageView赋值,更改frame,更改scrollView.contentSize三部操作。
private var image:UIImage? {
get {
return imageView.image
}
set {
imageView.image = newValue
imageView.sizeToFit()
scrollView.contentSize = imageView.frame.size
}
}
网友评论