内存管理方式(3种)
- MRC(Manual Reference Counting, 手动引用计数)
MRC:就是由程序员自己负责管理对象生命周期,负责对象的创建和销毁。
管理原则:需要手动添加retain、release来管理内存,遵循谁创建谁回收的原则
- ARC(Automatic Reference Counting, 手动引用计数)
ARC:采用与MRC一样的内存引用计数管理方法,但不同的是,它在编译时会在合适的位置插入对象内存释放(如release、autorelease和retain等),程序员不用关心对象释放的问题。苹果推荐在项目中使用ARC。ARC不能在iOS5之前的系统中使用。另外注意: 这一机制使得开发者无需键入 retain 和 release, 这不仅能够降低程序崩溃和内存泄露的风险, 而且可以减少开发者的工作量, 能够大幅度提升程序的流畅性和可预测性. 但是 ARC 不适用于 Core Foundation 框架中, 仍然需要手动管理内存.
管理原则:自动管理内存,自动释放池(autorelease pool),没有强引用指向对象,对象就会被释放
- GC (Garbage Collector, 垃圾回收机制)
GC:在OC2.0之后,内存管理出现了类似于JAVA和C#的内存垃圾收集技术,但与ARC完全不同,GC是后台有一个线程负责监察已经不再使用的对象,然后将它释放。由于后台一直有一个线程在运行,因此会严重影响性能,这也是Android(安卓)手机一直让人不爽的原因。*重点!CG技术不能应用于iOS开发,只能应用于Mac OS X 开发。
注意:iOS是手机端开发;MAC OS X 是电脑端开发
- 总结:iOS采用ARC和MRC这两种方式,ARC是苹果推荐的方式,MRC相对比较原始,对于程序员的能力要求很高,但是它很灵活、方便,很不容易驾驭。另外,Swift采用ARC管理内存。
-
MRC和ARC下的混编
在ARC的项目中,对MRC的文件可以添加编译选项-fno-objc-arc的标识;
在MRC的项目中,对ARC的文件可以添加编译选项 -fobjc-arc的标识;
步骤:Build Phases -> Compile Soueces
各属性解析
1)与retain配对使用的方法是release,因为retain是将内存的引用计数加一(对对象进行一次持有),release是将内存的引用计数减一(结束对对象的持有)。
2)与alloc对应的方法是dealloc,因为alloc表示开辟内存空间,创建对象,dealloc表示回收内存空间,释放对象。
3)readwrite表示读写设置中的可读可写(读写设置的默认值),编译器会为读写设置声明为”readwrite”的属性自动合成setter和getter方法。
4)readonly表示读写设置中的只读,编译器会为读写设置声明为”readonly“的属性自动合成”getter”方法,而不合成”setter“方法。
5)assign是语义设置(语义设置的默认值),使用assign修饰的属性所对应的读写方法中不会操作内存的引用计数,所以一般将不需要程序员管理的数据类型声明为assign,如基本数据类型和结构体类型。assign:默认类型,setter方法直接赋值,而不进行retain操作
6)retain是语义设置,使用retain修饰的属性所对应的读写方法中会对内存的引用计数进行操作,以保证持有的对象不会被意外回收,OC中的对象使用retain修饰。retain:setter方法对参数进行release旧值,再retain新值。
7)copy是语义设置,使用copy修饰的属性所对应的读写方法中会将将要持有的对象拷贝一份,并持有对象的副本而不是原对象。对于OC中的可变对象,使用copy修饰,是”深拷贝“,在内存中生成一块新的内存空间,将原对象拷贝到新空间中;对于OC中的不可变对象,使用copy修饰,是”浅拷贝“,只拷贝对象的内存地址。copy:setter方法进行Copy操作,与retain一样
8)atomic:是原子特性(原子设置的默认值),在多线程环境下,使用atomic会保证在同一时刻只有一条线程修改、访问对应的实例变量,保证了实例变量在多线程环境下的安全性,但是比较耗费资源,所以只有对于需要线程安全的属性才使用atomic来修饰。
注意: 它并不意味着线程是完全安全的, 它会增加正确的几率, 能够更好的避免线程的错误
9)nonatomic:是原子特性,在多线程环境下不能保证线程安全,这种设置不会消耗过多的资源,所以不需要保证多线程环境中线程安全的属性,声明为nonatomic。
10)strong:ARC中的语义设置,相当于MRC中的retain,会操作内存的引用计数。
11)week:ARC中的语义设置,相当于MRC中的assign,不仅不会操作内存的引用计数,而且在对象被回收后,会将指针置为nil,防止”野指针“的出现。 所以它可以用于避免两个强引用产生的循环引用导致内存无法释放的问题.
12) ** __block 和 __weak** 它们都用于修饰变量
- 前者用于指明当前声明的变量在被 block 捕获之后, 可以在 block 中改变变量的值. 因为在 block 声明的同时会截获该 block 所使用的全部自动变量的值, 而这些值只在 block 中只具有"使用权"而不具有"修改权". 而 __block说明符就为 block 提供了变量的修改权.
** __block在 ARC 下捕获的变量会被 block retain, 这样可能导致循环引用, 所以必须要使用弱引用才能解决该问题. 而在非 ARC 下, 可以直接使用 __block
说明符修饰变量, 因为在非 ARC 下**, block 不会 retain 捕获的变量.
- 后者是所有权修饰符, 什么是所有权修饰符? 这里涉及到另一个问题, 因为在 ARC 有效时, id 类型和对象类型同 C 语言中的其他类型不同, 必须附加所有权修饰符. 所有权修饰符一种有以下 4 种
。__strong
。__weak
。__unsafe_unretained
。__autorelease
13) __weak 与 weak 的区别只在于, 前者用于变量的声明, 而后者用于 属性的声明.
__weak typeof(self) weakSelf=self; 一般有block的地方都可用上这个, 以防万一出现循环引用
autorelease的使用问题
1.在MRC中,释放对象通过release或autorelease消息实现,其中release消息会立刻使引用计数减一,autorelease消息会使对象放入内存释放池中延迟释放,对象的引用计数并不变化,而是向内存释放池中添加一条记录,直到池被销毁前通知池中的所有对象全部发送release消息才真正将引用计数减少。
2.由于使用autorelease消息会使对象延迟释放,所以除非必须的情况,否则不要使用它释放对象。在iOS程序中,内存释放池的释放默认在程序结束。
- 我们可以在应用程序的主入口 main.m 中看到这段代码:在@autoreleasepool{...}之间的代码,就是池的作用范围,默认是整个应用。如果产生大量对象,采用autorelease释放也会导致内存泄漏。
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
- 什么时候使用autorelease呢?请看下面的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = @"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: CellIdentifier] autorelease];
}
return cell;
在上面的代码中,cell对象不能马上释放,我们需要使用它设置表示图的界面。autorelease一般用在为其他调用者提供对象的方法中,对象在该方法中不能马上释放,所以需要延迟释放。
其他补充



网友评论