Notes

ARC

属性声明与所有权修饰符的对应关系

属性声明 所有权修饰符
assign __unsafe_unretained
copy __strong 对象是被复制过来的
retain __strong
strong __strong
unsafe_unretained __unsafe__unretained
weak __weak

ARC的实现

__strong

关键函数

实例

源代码 1

{
	id __strong obj = [[NSObject alloc] init];
}
// 编译器模拟代码
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_release(obj); // 变量作用域结束时释放对象

源代码 2 - objc_retainAutoreleasedReturnValue

{
	id __strong obj = [NSMutableArray array];
}
// 编译器模拟代码
id obj = objc_msgSend(NSMutableArray, @selector(array));
objc_retainAutoreleasedReturnValue(obj);
objc_release(obj);

源代码 3 - objc_autoreleaseReturnValue

+ (id)array {
	return [[NSMutableArray alloc] init];
}
// 编译器模拟代码
+ (id)array {
	id obj = objc_msgSend(NSMutableArray, @selector(alloc));
	objc_msgSend(obj, @selector(init));
	return objc_autoreleaseReturnValue(obj);
}

__weak

关键函数

weak 表

对象释放的过程

  1. objc_release
  2. 引用计数为 0 -> 调用 dealloc
  3. _objc_rootDealloc
  4. object_dispose
  5. objc_destructInstance
  6. objc_clear_deallocating <- Magic Happens Here
    1. 从 weak 表中以该对象注册的所有 weak 记录
    2. 将 weak 记录中所有变量置为 nil
    3. 从 weak 表中删除对象
    4. 从引用计数表中删除以该对象地址为键值的记录

由于为 weak 表的弱指针置空包含了赋值操作,因此,若存在大量的 weak 指向,释放对象时,将会消耗大量的 CPU 资源,因此,只应该在需要避免循环引用的情况才使用

实例

源代码 1

{
	id __weak obj1 = obj;
}
// 编译器模拟代码
id obj1;
objc_initWeak(&obj1, obj);
objc_destroyWeak(&obj1);
// 将上面的代码再分拆

// objc_initWeak(&obj1, obj);
id obj1 = 0;
objc_storeWeak(&obj1, obj);

// objc_destroyWeak(&obj1);
objc_storeWeak(&obj1, 0);

__autoreleasing

关键函数

实例

重点都是有 objc_autorelease

源代码 1 - alloc - init

@autoreleasepool {
	id __autorelease obj = [[NSObject alloc] init];
}
// 编译器模拟代码
id pool = objc_autoreleasePoolPush();
id obj = objc_msgSend(NSObject, @selector(alloc));
objc_msgSend(obj, @selector(init));
objc_autorelease(obj);
objc_autoreleasePoolPop(pool);

源代码 2 - 类方法创建

@autoreleasepool {
	id __autorelease obj = [NSMutableArray array];
}
// 编译器模拟
id pool = objc_autoreleasePoolPush();
id obj = objc_msgSend(NSMutableArray, @selector(array));
objc_retainAutoreleasedReturnValue(obj);
objc_autorelease(obj);
objc_autoreleasePoolPop(pool);