iOS内存管理和多线程(1)

原文请见:http://qiita.com/ylisr/items/b404c8fc96945a6f613d

本文章是《Pro Multithreading and Memory Management》的读后笔记,包括ARC机制、Blocks和GCD(Grand Central Dispatch)的用法。

Objective-C中的内存管理操作——引用计数(Reference Counting)

Objective-C对象的操作
Objective-C方法
创建及保持对象
alloc/new/copy/mutableCopy group
保持对象
retain
释放对象
release
销毁对象
dealloc

+(id)alloc

implementation.m:

+ (id) alloc {
    return [self allocWithZone: NSDefaultMallocZone()]; 
}

+ (id) allocWithZone: (NSZone*)z {
    return NSAllocateObject (self, 0, z); 
}

struct obj_layout { 
    NSUInteger retained;
};

inline id NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone *zone) {
    int size = /* needed size to store the object */
    id new = NSZoneMalloc(zone, size);
    memset(new, 0, size);
    new = (id)&((struct obj_layout *)new)[1];
}

NSAllocateObject函数调用NSZoneMalloc来分配内存空间。之后空间被0填充,且空间指针被返回。现在,Objective-C忽略曾经用来防止内存碎片化的区域。alloc方法能够被重写为:

demo.m:

struct obj_layout { 
   NSUInteger retained;
};

+ (id) alloc {
   int size = sizeof(struct obj_layout) + size_of_the_object; 
   struct obj_layout *p = (struct obj_layout *)calloc(1, size); 
   return (id)(p + 1);
}

alloc方法返回一个被0填充、包括一个结构obj_layout头的内存块,它包含一个“retained”变量来存储引用次数。

retain

通过调用retainCount来获取引用计数值:

demo.m:

id obj = [[NSObject alloc] init]; 
NSLog(@"retainCount=%d", [obj retainCount]);
/* retainCount=1 is displayed. */

retain的执行:

demo.m:

- (id) retain{
    NSIncrementExtraRefCount(self);
    return self;
}

inline void NSIncrementExtraRefCount(id anObject) {
    if (((struct obj_layout *)anObject)[-1].retained == UINT_MAX - 1) 
    [NSException raise: NSInternalInconsistencyException
        format: @"NSIncrementExtraRefCount() asked to increment too far"];
    ((struct obj_layout *)anObject)[-1].retained++; }

当“retained”变量溢出时,它便进行递增。

release

demo.m:

- (void) release {
    if (NSDecrementExtraRefCountWasZero(self))
    [self dealloc]; 
}

BOOL NSDecrementExtraRefCountWasZero(id anObject) {
    if (((struct obj_layout *)anObject)[-1].retained == 0) { 
        return YES;
    } else {
        ((struct obj_layout *)anObject)[-1].retained--; return NO;
    } 
}

“retained”变量进行递减。

dealloc

demo.m:

- (void) dealloc {
    NSDeallocateObject (self); 
}

inline void NSDeallocateObject(id anObject) {
    struct obj_layout *o = &((struct obj_layout *)anObject)[-1];
    free(o);
}

内存块实行释放。

autorelease

和C语言中的“automatic variable”类似,当执行离开作用范围时,自动销毁。

autorelease意味着当执行离开程序块时,release方法被自动调用。

demo.m:

- (id) autorelease {
    [NSAutoreleasePool addObject:self]; 
}

ARC(自动引用计数)

使用ARC,“id”和对象类变量必须具有以下持有资格:

_strong,_weak,_unsafe_unretained,_autoreleasing

_strong:持有权被变量作用域/变量间赋值适当地管理。

_weak:用来避免循环引用

该持有资格提供弱引用,弱引用没有对象的持有权。

demo.m:

id __strong obj0 = [[NSObject alloc] init];
id __weak obj1 = obj0;
/* variable obj1 has a weak reference of the created object */

_unsafe_unretained:请勿使用除非你必须支持iOS5之前版本,因为它可能留下一个野指针。请使用_weak来替代。

然而,_weak仅专门应对于应被清零的指针,而不是原始类型。

_unsafe_unretained适用于当你有一个对象指针且ARC无法十分安全地管理内存的情况,比如一个常规C结构的内部。这也是有“在C结构中没有对象指针”限制的理由,除非你用_unsafe_unretained修饰这个指针来让编译器知道你在做什么。同时,它也用来在一些特殊环境下与blocks跳出强引用循环(又称为保留循环)。

但对于99.9%的工作,_weak工作得很好,完全可以忘记_unsafe_unretained。

Source










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值