1)一句话介绍
assign: 简单的赋值,不改变引用计数。(NSInteger 、int、 float、 char ...)
copy: 开辟新的内存,新建一个索引计数为1的对象,可释放旧对象。(NSString)
retain: 是说明该属性在赋值的时候,先release之前的值,然后再赋新值给属性,引用再加1。
readonly: 该对象只能读取,不能改写,只生成getter方法,不会生成setter方法。
readwrite: 可读可写的对象。
nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。
2)换句话说 assign and retain 有啥区别?
现在有这样一个场景,我分配了一块内存,并且把它的地址赋值给A指针。后来,我希望B指针也可以共享这块内存,于是乎,我又把A指针(内存地址)赋值给了B,这时候咧,A和B就同时拥有这块内存。
好了,
@property (assign, nonatomic) 类型名* A;
@property (retain, nonatomic) 类型名* B;
A =[ [ 类型名 alloc] init ] ; B = A ;
Q:请问当A不再需要这块内存,能否直接释放它?
A: 答案是否定的,因为A并不知道B是否还在使用这块内存,如果A释放了,那么B在使用这块内存的时候会引起程序crash掉。
Q: 那么如何解决?
A: 最简单的一个方法就是使用引用计数(reference counting)。我们给那块内存设一个引用计数,当内存被分配并且赋值给A时,引用计数是1。当把A赋值给B时引用计数增加到2。这时如果A不再使用这块内存,它只需要把引用计数减1,表明自己不再拥有这块内存。B不再使用这块内存时也把引用计数减1。当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以把它直接释放掉。
总的来说:assign就是直接赋值,从而可能引起上面的问题,当数据为int, float等原生类型时,可以使用assign。retain使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。
3)换句话说 copy 到底怎么用?
copy:是在你不希望A和B共享一块内存时会使用到。A和B各自有自己的内存。
NSString、NSArray、NSDictionary等等经常使用copy关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,为确保对象中的属性值不会无意间变动,应该在设置新属性值时拷贝一份,保护其封装性
block也经常使用copy关键字
block 使用 copy 是从 MRC 遗留下来的“传统”,在 MRC 中,方法内部的 block 是在栈区的,使用 copy 可以把它放到堆区.
在ARC中写不写都行:对于 block 使用 copy 还是 strong 效果是一样的,但是建议写上copy,因为这样显示告知调用者“编译器会自动对 block 进行了 copy 操作”
4)nonatomic 和 atomic 的又怎么说?
【摘自网络 侵删】
atomic:默认是有该属性的,这个属性是为了保证程序在多线程情况下,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题。
nonatomic:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。
atomic的意思就是setter/getter这个函数,是一个原语操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行完setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加了锁一样,可以保证数据的完整性。nonatomic不保证setter/getter的原语行,所以你可能会取到不完整的东西。因此,在多线程的环境下原子操作是非常必要的,否则有可能会引起错误的结果
- (void)setCurrentImage:(UIImage *)currentImage{
NSLock *lock = [[NSLock alloc]init];
[lock lock];
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
// do something
}
}
可以看出来,用atomic会在多线程的设值取值时加锁,中间的执行层是处于被保护的一种状态,atomic是oc使用的一种线程保护技术,基本上来讲,就是防止在写入未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。