23章:避免内存泄漏

避免内存泄漏

事物之间的关系通常是双向的。

在BNRAsset.h中增加一个指针类型的实例变量,用于保存BNREmployee对象。

代码如下:

@class BNREmployee;

@interface BNRAsset : NSObject
@property (nonatomic , copy) NSString *label;
@property (nonatomic) BNREmployee *holder;
@property (nonatomic) unsigned int resaleValue;
@end

在BNRAsset.m中,扩充description,使其返回的字符串能够提现新增加的实例变量holder。

在BNREmployee中加入addAsset。

强引用循环

BNRAsset对象拥有BNREmployee对象,BNREmployee对象拥有包含BNRAsset对象拥有包含BNRAsset对象的数组,改数组对象又拥有BNRAsset对象。这种“互相拥有”的所有权关系导致的相关的对象都无法被释放。这种情况被称为强引用循环,强引用循环是导致内存泄漏的常见原因。

Instrument 可以找出程序中的强引用循环。为了有时间完成性能分析,需要在main()函数的末尾调用sleep()函数

Xcode->product->Profile->leak->Allocations会显示一个柱状图。

检查是否有强引用循环,点击Leaks,并在下拉列表中选择Cycles&Roots。

弱引用23

通过弱引用,可以解决强引用循环的问题。弱引用是不说明所有权的指针。要解决项目中的强引用问题,就不能让BNRAsset对象拥有它的holder。编辑BNRAsset.h,将holder改为弱引用。代码如下:

@property (nonatomic, weak) BNREmployee *holder;

如果对象间是父-子关系,那么未来避免强引用循环,通常需要遵守此规则:父对象拥有子对象,但是子对象不拥有父对象。

弱引用的自动置零特性

强引用会保留对象的拥有方,使其不被释放。而弱引用则不会被保留,因此标为弱引用的实例变量与属性指向的对象可能会消失,如果发生了这种情况,那么这个实例变量或属性会被设为nil。而不是继续指向曾经指向的对象。

手动引用计数和ARC历史

手动引用计数,release 失去一个拥有方,retain会得到一个拥有方。

你可能感兴趣的:(23章:避免内存泄漏)