关于loadView()与viewDidLoad()的职责划分及技术限制问询
关于
loadView()与viewDidLoad()的职责边界与技术限制 作为常年和iOS视图生命周期打交道的开发者,我来给你梳理清楚这两个方法的官方规则、职责划分以及实打实的技术限制,完全对应你关心的官方资料要求:
一、官方明确的职责划分
苹果对这两个方法的定位是非常清晰的:
loadView()的唯一核心职责就是创建并赋值视图控制器的view属性。你完全可以在这里用代码搭建整个视图层级,但要注意:别在这里做视图配置、数据填充这类后续操作,而且纯代码搭建时不要调用super.loadView()(除非你是基于父类已有的view扩展)。viewDidLoad()是在view被成功创建并加载后触发的,官方设计它的目的就是用来做视图的精细配置、子视图属性设置、数据绑定/加载这类工作——简单说,就是等你确定视图已经存在且可以安全访问时,做那些依赖视图存在的后续操作。
二、重写loadView()后,viewDidLoad()是否冗余?
绝对不冗余!哪怕你在loadView()里把所有子视图都创建好了,viewDidLoad()依然有不可替代的作用:
- 比如你在
loadView()里创建了一个UITableView,没必要在这里设置delegate、dataSource,也不用调用reloadData()——这些放在viewDidLoad()里更符合职责分离的设计,代码可读性也更高。 - 另外,像监听通知、初始化网络请求这类和视图创建无关,但依赖视图控制器生命周期的操作,也应该放在
viewDidLoad()里。
三、有没有必须放在viewDidLoad()的技术限制?
有!苹果官方文档明确指出,有些操作在loadView()中执行会出问题,必须推迟到viewDidLoad():
- 访问容器控制器关联属性:如果你在
loadView()里尝试访问navigationController、tabBarController这些父容器,很大概率会得到nil——因为此时视图控制器还没完全被加入到容器的层级中,这些关联对象还未被赋值。而viewDidLoad()调用时,视图控制器已经完成了和容器的绑定,这些属性可以正常访问。 - 避免递归调用风险:如果你在
loadView()里不小心调用了self.view的getter方法,会触发递归调用loadView()(因为当view为nil时,调用getter会自动触发loadView()),这是个常见的坑。而viewDidLoad()里就不会有这个问题,因为此时view已经完全创建好了。 - 调用需要视图上下文的API:比如某些Core Graphics绘制操作、
view.layer的复杂配置(阴影、圆角组合设置),虽然loadView()里也能调用,但官方更推荐在viewDidLoad()里做,因为此时视图初始化流程完全完成,不会出现上下文未准备好的异常。
内容的提问来源于stack exchange,提问作者Jumhyn
相关产品推荐
相关产品推荐

