免费开源的iOS开发学习平台

Objective-C内存管理

内存管理的核心工作就是及时清理回收不用的内存空间,以便高效的利用内存空间。在面向对象编程开发中,内存管理的核心就是管理对象的释放。当一个对象不再被使用时,需要及时从内存中清除。

引用计数(Reference Count)

引用计数是在Objective-C中用于管理对象生命周期的机制,这种机制可以很有效的管理对象的生命周期。当一个对象被创建时,它的引用计数为1。每当有新的指针指向这个对象时,这个对象的引用计数就加1。当某个指针不再指向这个对象时,该对象的引用计数减1。当该对象的引用计数为0时,该对象就被自动销毁,占用的内存被回收。

对于引用计数的理解,也可以用放风筝做个比喻。比如说风筝就是一个对象,最开始时,会有一个人拉着一根线不让风筝飞走,当再有人来时,会给这个风筝再加1根线,这时,这个风筝就有两根线牵着,其中任何一根线断掉,风筝都不会飞走,只有当两根线都断掉时,风筝才会飞走。引用计数也基本符合这个道理。

MRC(Manual Reference Counting)

MRC,即手工引用计数。在Xcode4.2版本之前,对象的引用计数都需要程序员来手工管理,因此,程序员需要花费大量的经历来管理对象的创建与销毁,其中一个最基本的原则就是:谁创建谁销毁。

在MRC中,程序员需要手工管理对象的引用计数,在NSObject类中,有关引用计数有如下常用方法。

  • 引用计数加一
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
  • 引用计数减一
- (oneway void)release OBJC_ARC_UNAVAILABLE;
  • 获取对象当前的引用计数
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;

MRC测试

  • 新建一个命令行工具工程

  • 在TARGETS设置中,为main.m文件添加-fno-objc-arc编译标示

  • 在main.m文件,编写如下的代码。创建一个对象obj1,并且创建obj2,指向obj1,然后释放obj2以及obj1,打印在不同时间点obj1的引用计数。
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj1 = [[NSObject alloc] init];
        NSLog(@"obj1 当前引用计数:%lu",(unsigned long)[obj1 retainCount]);
        NSObject *obj2 = [obj1 retain];
        NSLog(@"obj1 当前引用计数:%lu",(unsigned long)[obj1 retainCount]);
        [obj2 release];
        NSLog(@"obj1 当前引用计数:%lu",(unsigned long)[obj1 retainCount]);
        [obj1 release];
    }
    return 0;
}
  • 运行结果。我们可以obj1的引用计数的变化过程

ARC(Automatic Reference Counting)

随着Xcode4.2的发布,苹果引入了其中一个新特性就是自动引用计数(ARC:Automatic Reference Counting)。与MRC不同,自动引用计数(ARC)模式中,对象的引用计数管理完全交由系统来管理,也就是说,在MRC中的retain/release操作都由系统自动完成了。程序员90%的情况下,不需要去再关系内存管理相关的事务,对象的释放完全交由系统来统一管理。目前ARC已经成为iOS程序开发的主流选择,这也是苹果所希望看到的。使用自动引用计数ARC可以避免程序员因为疏忽而造成的引用计数出错的隐患,不仅极大的简化了代码编写工作量,同时也减少了内存管理中存在的错误。

示例代码

https://github.com/99ios/6.2