⚠️ 可能会出现的BUG: View的懒加载执行了两次alloc
最近写代码时候遇到了懒加载执行两次的问题。代码如下
@interface ViewController : UIViewController
@property (nonatomic, strong) UITableView *tableView;
@end
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(0);
}];
}
/// 懒加载
- (UITableView *)tableView{
if (!_tableView) {
// self.view 可能会导致此处创建两次
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
// 应改为⬇️
// _tableView = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
_tableView.contentInset = UIEdgeInsetsMake(70, 0, 0, 0);
}
return _tableView;
}
正常的情况下,上面的代码不会出现任何问题。代码执行的顺序 viewDidLoad
-> self.tableView
-> self.tableView懒加载创建
->addSubview:
最后展示在view上面
这里会涉及一个概念: viewDidLoad什么时候调用
个人浅层理解:viewDidLoad 就是 vc.view的懒加载。只会执行一次
这里有更详细的图文讲解
出现问题的场景:在[[vc alloc] init]
之后 -> 外部调用并使用了vc.tableView
->[push:vc]
之前
这个时候上面的代码就会出现tableView
的懒加载alloc
两次的问题
问题原因: 代码顺序
-
[[vc alloc] init]
vc初始化 - 外部调用了
vc.tableView
执行tableView
的懒加载。 - 这时
_tableView == nil
执行了创建方法 - 因为
tableView
创建的时候使用了self.view.bounds
从而触发了viewDidLoad
方法 -
viewDidLoad
内部引用了self.tableView
执行懒加载(get方法) - 这时
_tableView == nil
仍然为空。再次执行创建方法 - 最终导致了
alloc
两次。
解决方法
将self.view.bounds
替换为[UIScreen mainScreen].bounds
疑问
为什么创建的时候Frame
不采用CGRectZero
。毕竟后面也用了Masonry