首先 对ARC(AutomaticReference Counting)进行了解。ARC技术是能提供自动引用技术,省掉了让人烦人和容易遗漏的retain,release,autorelease等操作,其工作原理是将内存操作的代码(retain,release等)自动添加到需要的位置。即底层上使用和MRC手工引用技术一样的内存管理机制。需要注意的是:ARC是编译器(时)特性,而不是运行时特性。
紧接着我们来谈谈ARC与MRC的问题:
(1)修饰属性(使用@property定义时)
读写控制:
readwrite:可读可写,会生成getter和setter方法。
readonly:只读,只会生成getter方法,不会生成setter方法。
引用方式:
copy:拷贝,复制一个对象并创建strong关联,引用计数为1 ,原来对象计数不变。
assign:赋值,不涉及引用计数的变化,弱引用。ARC中对象不能使用assign,但原始类型(BOOL、int、float)仍然可以使用。
retain:持有,对原对象引用计数加1,强引用。ARC中使用strong。
weak:赋值(ARC),比assign多了一个功能,对象释放后把指针置为nil,避免了野指针。
strong:持有(ARC),等同于retain。
线程安全:
nonatomic:非原子操作,不加同步,多线程访问可提高性能,但不是线程安全的。
atomic:原子操作,与nonatomic相反。
(2)修饰变量(修饰不使用@property定义时,比如函数内的局部变量)
__strong:是缺省的关键词,强引用。
__weak:声明了一个可以自动置nil的弱引用(ARC中)。
__unsafe_unretained:声明一个弱引用,但是不会自动nil化(只有iOS 4 才应该使用)。
__autoreleasing:用来修饰一个函数的参数,这个参数会在函数返回的时候被自动释放(类似autorelease)。
这是一些概念上得不同。
这时候,我们就要问__strong,__weak 是怎么一回事,那么我们就介绍一下,强引用 与弱引用的问题:
强引用:当前对象被其他对象引用时,会执行retain操作,引用计数器+1。当retainCount=0时,该对象才会被销毁。因为我们要进行对象的内存管理,所以这是默认的引用方式。(默认是强引用)
弱引用:当前对象的生命周期不被是否由其他对象引用限制,它本该什么时候销毁就什么时候被销毁。即使它的引用没断,但是当它的生存周期到了时就会被销毁接下来,在谈谈block 的引用问题:
在MRC中,用__block 修饰变量,他起到的作用是:
1.说明变量课改
2.说明指针指向的对象不做这个隐式的retain操作
然而,在ARC中,使用
__block __typeof(self) weakSelf = self;
calendar.tapDate = ^(NSString *date){
[weakSelf sayHi];
};
发现 程序出现循环引用,无法释放内存的问题;
然后这样写:
__weak __typeof(self)weakSelf = self;
calendar.tapDate = ^(NSString *date){
[weakSelf sayHi];
};
是没有问题;
既然都是让block中捕获的指针指向的对象不要进行retain 操作,为何在ARC中__block就不起作用呢?
我认为:在ARC中,block的运行机制发生了变化,对__block 的捕获进行了修改,导致这个关键词失去了作用。
注意:(在Cocoa中: 在ARC引入后,没有了retain和release等操作,情况也发生了改变:在任何情况下,__block修饰符的作用只有上面的第一条:说明变量可改。即使加上了__block修饰符,一个被block捕获的强引用也依然是一个强引用)这句话的表述是有误的。ARC中仍然有retain 和release 操作。
因此:__block的两个作用都在,但是ARC捕获机制发生改变,不认识__block修饰的变量不进行retain操作。
这时候有又一个新问题出现:__weak在弱引用,在一般的单线程环境中,这种问题出现的可能性不大,但是到了多线程环境,就很不好说了,所以我们需要继续完善这个方法:
__weak __typeof(self)weakSelf = self;
calendar.tapDate = ^(NSString *date){
__strong __typeof(weakSelf) strongSelf = weakSelf;
[strongSelf sayHi];
};
OK,到此解决问题。
下边附上注意事项:
1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。
3.__block对象可以在block中被重新赋值,__weak不可以。
参考:http://www.cocoachina.com/ios/20150206/11121.html