ARC:
指定文件编译时用 ARC 机制,指定编译属性:-fobjc-arc,非 ARC :_fno-objc-arc
1.黄金法则:
对象调用一次:alloc new copy mutablecopy(自己生成并持有的) retain(非自己生成,而持有的)
就必须调用一次:release autorelease(对自己持有的对象可以进行 release autorelease)
2.工厂方法
Foundation 提供的工厂方式的实现:
+ (id) object
{
// 自己生成并持有
id obj = [[NSObject alloc] init];
// 放到自动释放池中管理,该方法可以取得对象的存在,但是自己不持有
[obj autorelease];
return obj;
}
一般情况下自己实现的工厂方法
+ (id) object
{
// 自己生成并持有
id obj = [[NSObject alloc] init];
// 没有放到自动释放池中管理该对象
return obj;
}
所以:Foundation提供的工厂方法获得对象不能调用 release autorelease,因为里面已经存在了autorelease
一般自己实现的工厂方法是可以调用 release autorelease 方法的
3.autorelease的内部实现 (GNUstep)
- (id)autorelease
{
[NSAutoreleasePool addObject:self];
}
autorelease实例方法的本质就是调用 NSAutoreleasePool对象的 addObject:方法,把对象添加到自动释放池中
4.所有的权限修饰符:__strong __weak __unsafe_unretained __autoreleasing
1> __strong
__strong 强应用,默认变量的类型
__strong修饰的变量 obj 在超出其变量的作用域时,会释放其被赋予的对象。
注意:强引用之间的赋值对内存的影响。
2> __weak
__weak 弱引用
__weak 只有用在 ARC 机制下,作用才能显示出来。
在持有某对象的弱引用时,该对象被废弃,此弱引用将自动失效且处于nil 被赋值的状态。
还有一个作用就是防止循环强引用。
3> __unsafe_unretained
__unsafe_unretained在低版本中替代__weak的
作用:__unsafe_unretained 和 __weak 一样,自己生成的对象自己不能持有,也就是在生成销毁
4> __autoreleasing
在 ARC 有效时,不能使用 NSAutoreleasePool 和 autorelease
用@autoreleasepool 替代 NSAutoreleasePool
用__autoreleasing 替代 autorelease将对象赋值给用__autoreleasing 修饰的变量等价于对象调用了 autorelease方法
__strong __weak __autoreleasing 可以将修饰的变量初始化为 nil
5.属性
属性声明与所有权修饰符之前的对应关系
assign:__unsafe_unretained
copy:__strong
retain:__strong
strong:__strong
unsafe_unretianed:__unsafe_unretained
weak:__weak
Block
block是 C 语言的扩充:带有自动变量的匿名函数
1.block语法与一般的 C 语言函数相比的差别:
1> 没有函数名
2> 带有^
第一点不同因为他是匿名函数,第二点不同是返回值前带有^
2.语法格式:
1> ^ 返回值类型 参数列表 表达式
^int (int count){
return count+1;
}
Block 的省略
2> ^ 参数列表 表达式
返回值类型可以根据return 的类型来推断
^(int count){
return count + 1;
}
3> ^ 表达式
返回值类型和参数列表都被省略
^{
printf("Blocks\b");
}
3.block类型的变量
返回类型 (^变量名)(参数)
// 声明了一个 blk变量
int (^blk)(int);
Block 类型的变量和C 语言的函数指针的差别
就是变量前的* 换成了 ^
4.自动变量
在 block 中获取外部变量的值存储在 block 自带的自动变量中,以后再改变外部变量的值,block 内部的自动变量值不会改变。
int main(){
int val = 0;
// 定义一个 block 变量并赋值
void(^blk)(void) = ^{
// val 是 block 自带的自动变量值
printf("val = %d\n",val);
};
// 调用 block 方法 输出 val = 0;
blk();
// 改变外部变量的值
val = 1;
// 再次调用 block 方法 输出 val = 0
blk();
}
不能在 block 内部改变外部变量的值
__block修饰的变量可以在 block 中赋值,该变量称为__block变量
Block 是存在栈上的实例变量
栈的 block 复制到堆上调用的函数 copy
堆上 block 被废弃是调用函数 dispose 函数
什么时候栈上 block 会复制到堆上
1> 调用 block 的 copy 实例方法
2> block 作为函数返回值时
3> 将 block 赋值给有__strong 修饰的id 类型或 block 类型
Block循环引用
对象拥有 block 实例变量,block 中拥有对象的 self。
会引起循环引用,所以要把 block 实例变量前加 __weak
__block 来避免循环引用,定义一个__block类型的变量,然后将 self 赋值给他。__block变量持有对象还持有Block ,对象持有 block