前言
前两篇中 Objective-C 属性,在定义属性时我们使用一系列关键字,比如:retain,release,assgin,copy,strong,weak 等等,那么这些关键字到底在程序运行起什么作用呢? 下面我们通过内存管理来深刻的理解这些词的具体作用。
介绍
内存管理:程序在运行过程中,会创建很多的类和对象,而创建类和对象就要占用内存空间,基本类型都是系统自动管理放在栈区,而创建的类和对象放在堆区,我们得手动管理这篇区域的内存使用情况。
Objc 作为高级程序语言是怎么管理的呢? 像 java 内存管理有垃圾回收机制 (gc),Objc 的内存并没有垃圾回收机制,难道让我们自己去内存中找到对应地址释放内存吗,当然不是如果是这样就脱离高级语言了,我们要引入 "引用计数器" 我们通过这个管理内存。我们先来看看这个神秘东东的介绍吧。
引用计数器
引用计数器:Objc 在创建类和对象的时候,内部会默认给类和对象添加一个计数器一样的属性 (retainCount),来表明其使用情况。当一个类和对象的时候,这个计数器(retainCount) 就会加 1,在不适用这个类的时候,计数器减 1,当计数器为 0 时,就会释放内存空间。
retain,copy 计数器就会 + 1; 而我们在创建类和对象所使用的 new 和 alloc 同样也会使计数器 + 1.
当我们调用 release 的时候计数器相对应 - 1,当计数器为 0 时,自动调用 dealloc 方法释放内存。
Objc 目前为我们提供了两种内存管理,MRC 和 ARC 分别为手动内存管理和自动内存管理,ARC 是从 Xcode4.2 开始使用的,也是苹果公司推荐的内存管理方式。以下我们详细介绍这两种。
MRC 手动内存管理
MRC(MannulReference Counting)手动内存管理,顾名思义就是需要我们 (开发者) 管理每一个使用的类和对象,手动编写 retain 和 release,需要我们对内存的管理更加深刻。当然想要更加深刻学习 Objc 内存管理还是来使用 MRC 吧。在痛苦中挣扎,黑暗中觉醒,哈哈。
现在默认是 ARC,使用 MRC 需要我们手动开启:项目属性—Build Settings–搜索 "garbage" 找到 Objective-C Automatic Reference Counting 设置为 NO。
我们将通过一个 Person 类来学习
- #import@interface Person: NSObject#pragma mark - 属性@property(nonatomic, copy) NSString * name;@property(nonatomic, assign) NSInteger age;@end#import "Person.h"@implementation Person //重写dealloc方法 方便观察-(void)dealloc{NSLog(@"Invoke Person's dealloc method.");[super dealloc];}-(void) test{Person *teach = [[Person alloc]init]; //alloc 开辟内存空间 引用计数器+1teach.name = @"gavin";teach.age = 26;Person *student = [Person new]; //new 相当于alloc + init 同样开辟内存空间 引用计数器+1student.name = @"alice";student.age = 20;//这个时候我们不需要teach这个对象要释放[teach release]; //如果我们使用这样的方法,teach指针指向的内存空间释放了,但是这个指针还是存在的,那么我以后如果不小心调用这个指针,有可能得到一个异常的结果,或者直接崩溃。这就是野指针也就是空指针。//正确的使用姿势//首先让指针为空teach = nil;[teach release];//使用retain,使得引用计数器+1[student retain];//可以查看引用计数器变化NSLog(@"retainCount=%lu",[p retainCount]);//使用release,引用计数器-1[student release];//使用copy查看内存变化Person *alice = [teach copy];/*使用copy,需要注意看我们的具体需要:这里面涉及深拷贝和浅拷贝。深拷贝:mutableCopy 相当于复制一个副本,原件的改变不会影响副本。浅拷贝:copy 相当retain,使当前对象teach的引用计数器+1;*/}
内存的释放
内存的释放遵循:谁创建,谁释放 的原则,而往往在实际开发过程错综复杂调用和对象之间相互交叉引用使得这个过程相对不是那么容易。ARC 的出现使得开发者效率大大提高。但是在内存使用也需要注意循环引用。
ARC 自动内存管理
ARC(Automatic Reference Counting)自动内存管理,相比较 MRC,我们 (开发者) 不需要在内存管理上花费大量的开发时间,我们可以专注的开发业务代码,调用相应的方法,在程序编译的时候自动帮我们加上 retain 和 release。
ARC 具体介绍可以查看 官方文档 摘出来一些方便查看:
变量修饰符可以使用如下修饰符:
__strong
__weak
__unsafe_unretained
__autoreleasing
__strong: 默认限定符,不需要显式指定。表示任何用 alloc/init 创建的对象在当前范围的生命期内得以保留。"当前范围" 是指变量声明语句所在的两个大括号之间 (方法、循环、块,等等)。
__weak: 表示对象可以随时被摧毁。只有当它被其它对象强引用时才有用。__weak 变量在摧毁时,被设为 nil。
__unsafe_unretained: 与__weak 类似,但在摧毁时,不设为 nil,保留原值 (不再指向有效的东西)。
__autoreleasing: 不要与 autorelease 搞混,它用于通过引用传递对象,比如,通过引用传递 NSError 对象: [myObject performOperationWithError:&tmp]。
@autoreleasepool 自动释放池
在 ObjC 中也有一种内存自动释放的机制叫做 "自动引用计数"(或" 自动释放池 "),一般给只使用一次的对象发送这样的消息。如:
Person *teach = [[[Person alloc]init]autorelease];// 这样用是姿势不对
// 我们看看正确姿势
// 首先我们建立自动释放池
- id pool = [[NSAutoreleasePool alloc]init];
// 创建对象
- Person *teach = [[Person alloc]init];
// 添加自动释放
[teach autorelease];
// 这个时候我们添加到自动释放池中,只要缓存池没有释放,对象依然可以使用
- teach.name = @"gavin";
//pool 缓存池释放
- [pool release];
就爱阅读 www.92to.com 网友整理上传, 为您提供最全的知识大全, 期待您的分享,转载请注明出处。
来源: