iOS中结合代码看内存管理(一)

阅读本文前,建议移步先去了解下内存管理相关知识。

1: iOS内存管理机制(百度goole大法可以获得很多推荐)。

2: iOS中的动态内存分配

3: 堆栈的原理:堆栈 百科

1:自动释放池的常见问题:

较大的循环时如果不及时释放,可能会导致内存暴涨。

for (int i = 0; i < 100000; i ++) {

@autoreleasepool {  //解决方案:逐条释放,避免暴涨

NSString * log  = [NSString stringWithFormat:@"%d", i];

NSLog(@"%@", log); }

}

2: 修饰符的常见问题:

ARC提供四种修饰符,分别是strong, weak, autoreleasing, unsafe_unretained

__strong:强引用,持有所指向对象的所有权,无修饰符情况下的默认值。如需强制释放,可置nil。

比如我们常用的定时器:

NSTimer * timer = [NSTimer timerWith...];

相当于

NSTimer * __strong timer = [NSTimer timerWith...];

当不需要使用时,强制销毁定时器

[timer invalidate];

timer = nil;

__weak:弱引用,不持有所指向对象的所有权,引用指向的对象内存被回收之后,引用本身会置nil,避免野指针。

比如避免循环引用的弱引用声明:

__weak __typeof(self) weakSelf = self;

ps: 诸如网络请求的时候避免弱指针丢掉,往往需要在block内部从新strong下该指针。

__strong __typeof(weakSelf) strongSelf = weakSelf;

__autoreleasing:自动释放对象的引用,一般用于传递参数

比如一个读取数据的方法

- (void)loadData:(NSError **)error;

当你调用时会发现这样的提示

NSError * error;

[dataTool loadData:(NSError *__autoreleasing *)]

这是编译器自动帮我们插入以下代码

NSError * error;

NSError * __autoreleasing tmpErr = error;

[dataTool loadData:&tmpErr];

__unsafe_unretained:为兼容iOS5以下版本的产物,可以理解成MRC下的weak,现在基本用不到,这里不作描述。

3.  属性的内存管理

ObjC2.0引入了@property,提供成员变量访问方法、权限、环境、内存管理类型的声明,下面主要说明ARC中属性的内存管理。

属性的参数分为三类,基本数据类型默认为(atomic,readwrite,assign),对象类型默认为(atomic,readwrite,strong),其中第三个参数就是该属性的内存管理方式修饰,修饰词可以是以下之一:

1)assign:直接赋值

assign一般用来修饰基本数据类型

@property (nonatomic, assign) NSInteger count;

当然也可以修饰ObjC对象,但是不推荐,因为被assign修饰的对象释放后,指针还是指向释放前的内存,在后续操作中可能会导致内存问题引发崩溃。(!!!!!bug预警)

2)retain:release旧值,再retain新值(引用计数+1)

retain和strong一样,都用来修饰ObjC对象。

使用set方法赋值时,实质上是会先保留新值,再释放旧值,再设置新值,避免新旧值一样时导致对象被释放的的问题。

MRC写法如下

- (void)setCount:(NSObject *)count {

[count retain];

[_count release];

_count = count;

}

ARC对应写法

- (void)setCount:(NSObject *)count {

_count = count;

}

3)copy:release旧值,再copy新值(拷贝内容)

一般用来修饰String、Dict、Array等需要保护其封装性的对象,尤其是在其内容可变的情况下,因此会拷贝(深拷贝)一份内容給属性使用,避免可能造成的对源内容进行改动。

使用set方法赋值时,实质上是会先拷贝新值,再释放旧值,再设置新值。

实际上,遵守NSCopying的对象都可以使用copy,当然,如果你确定是要共用同一份可变内容,你也可以使用strong或retain。

@property (nonatomic, copy) NSString * name;

4)weak:ARC新引入修饰词,可代替assign,比assign多增加一个特性(置nil,见上文)。  weak和strong一样用来修饰ObjC对象。

使用set方法赋值时,实质上不保留新值,也不释放旧值,只设置新值。

比如常用的代理的声明    

 @property (weak) id delegate;

Xib控件的引用

@property (weak, nonatomic) IBOutlet UIImageView *productImage;

5)strong:ARC新引入修饰词,可代替retain

可参照retain,这里不再作描述。

4. block的内存管理

iOS中使用block必须自己管理内存,错误的内存管理将导致循环引用等内存泄漏问题,这里主要说明在ARC下block声明和使用的时候需要注意的两点:

1)如果你使用@property去声明一个block的时候,一般使用copy来进行修饰(当然也可以不写,编译器自动进行copy操作),尽量不要使用retain。

@property (nonatomic, copy) void(^block)(NSData * data);

2)block会对内部使用的对象进行强引用,因此在使用的时候应该确定不会引起循环引用,当然保险的做法就是添加弱引用标记。

__weak typeof(self) weakSelf = self;

你可能感兴趣的:(iOS中结合代码看内存管理(一))