深入详解 IOS strong 和 weak
今天写点深刻的关于内存管理的东西
IOS 采用arc 管理内存 让程序员不在纠结于内存的开辟释放等繁琐的工作
让内存管理更加简单
arc 是类似于垃圾回收机制 当一个对象没有一个强引用 指向它的时候 该 对象就会被自动释放
当一个对象被引用一次 就会给计数器加1 当对象的计数器变为0的时候就会被arc机制 回收
所以 记住一个原则 : 至少有一个强引用指向的对象才不会被销毁
科普一下 引用 有两种 strong (强引用) 和weak(弱引用)
下面通过一个非常深刻的问题来解释 strong和 weak的 使用
1.为什了控件的属性可以用strong 也可以用weak 对使用效果没有影响 而 代理必须用weak?
首先看 控件属性 假设 有一个 按钮(UIButton) 被添加到了 控制器的View上
那么相当于 :
UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];
[self.view addSubview:btn];
self.view 有一个 子控件数组 self.view.subviews
它是一个数组 NSArray *subviews
这个时候 就有一个 强引用 在数组中 指向我们的按钮 btn
而控制器 这个时候还可以通过连线 或者直接添加属性的方式对按钮进行引用
@property (nonatomic , weak)UIButton *btn;
如果是控制器的属性是weak 按钮就有一个弱指针(控制器的属性) 和一个强指针(self.view的数组)指向它 只要有一个强引用指向它 对象就不会被销毁 所以 这个时候 按钮是存在的
知道 控制器的View 被销毁 View的数组也会被销毁 按钮的强引用就不在了 这个时候按钮只有一个控制器的weak属性来指向它 所以也会被销毁
如果是控制器的属性是strong 按钮就有两个强引用 指向它
等控制器的View 销毁的时候 按钮还不会被销毁 因为控制器的属性还引用着 会不会出现野指针的问题呢?
当然不会 因为 控制器的销毁和view的销毁 是一致的 view
View都不在的时候 控制器也已经不在了
所以 控制器 中 连线 或者 设置 控件的属性的时候 可以用 stong 也 可以用 weak
接下来 看 在代理中 为什么 只能用weak 而不能用strong
以UITableView 为例 它有两个属性
@property (nonatomic, assign) id <UITableViewDataSource> dataSource;
@property (nonatomic, assign) id <UITableViewDelegate> delegate;
都是weak
UITableView 会在 UITableViewController控制器中
那么控制器有一个强引用 指向UITableView
谁来充当 UITableView的代理和数据源呢 ?
我们都知道一般都是控制器来充当
那么 UITableView 就有两个属性 引用着控制器
若果 这两个属性都是 强引用 那么控制器在UITableView释放之前就不会被释放 因为UITableView在 代理和数据源属性就在 控制器就在
而UITableView被控制器强引用着 控制器在 UITableView就在 这样至少要有一个 对象被释放另一个才能被释放
他们互相引用着对方 所以知道程序结束 控制器销毁 UITableView 才能被销毁 控件的生命周期和整个应用程序一样了 这是很可怕的
深究一下 其实控制器 不需要 UITableView来强引用
因为控制器会被添加到 它的父控制器的子控制器数组中 或者
被添加到根视图控制器中 所以 控制器的生命周期和它的父控制器是绑定的(由父控制器来决定当前控制器的死活) 一层一层的上溯 直到UIWindow *window 的
window.rootViewController 又直到AppDelegate
所以 代理设置成weak 就能避免这种相互包含的情况
父控制器 有权结束当前控制器 把当前控制器干掉了
UITableView的代理和数据源是weak 所以控制器会被销毁
那么 UITableView也就失去了强引用 随即被销毁
总结一句 : 代理必须用weak 控件 可以strong 可以weak
其实 不用去死记 一个对象是不是该存在 都能找到最应该决定它生命周期的那个对象
实线是强引用 虚线 是弱引用
欢迎探讨任何IOS开发的问题 请注明来自博客园 QQ:137569752 莫妄莫念