assign: 简单赋值,不更改索引计数
copy: 创建一个索引计数为1的对象,而后释放旧对象
retain:释放旧的对象,将旧对象的值赋予输入对象,再提升输入对象的索引计数为1多线程
Copy实际上是创建了一个相同的对象,而retain不是:
好比一个NSString对象,地址为0×1111,内容为@”STR”
Copy到另一个NSString之 后,地址为0×2222,内容相同,新的对象retain为1, 旧有对象没有变化并发
retain到另一个NSString之 后,地址相同(创建一个指针,指针拷贝),内容固然相同,这个对象的retain值+1函数
也就是说,retain是指针拷贝,copy是内容拷贝。在拷贝以前,都会释放旧的对象。性能
* 使用assign: 对基础数据类型 (NSInteger)和C数据类型(int, float, double, char,等)
* 使用copy: 对NSString
* 使用retain: 对其余NSObject和其子类atom
1.readonly表示这个属性是只读的,就是只生成getter方法,不会生成setter方法.
2.readwrite,设置可供访问级别
3.retain,是说明该属性在赋值的时候,先release以前的值,而后再赋新值给属性,引用再加1。
4.nonatomic,非原子性访问,不加同步,多线程并发访问会提升性能。注意,若是不加此属性,则默认是两个访问方法都为原子型事务访问。.net
retain和copy还有assign的区别线程
1. 假设你用malloc分配了一块内存,而且把它的地址赋值给了指针a,后来你但愿指针b也共享这块内存,因而你又把a赋值给(assign)了b。此时a和b指向同一块内存,请问当a再也不须要这块内存,可否直接释放它?答案是否认的,由于a并不知道b是否还在使用这块内存,若是a释放了,那么b在使用这块内存的时候会引发程序crash掉。指针
2. 了解到1中assign的问题,那么如何解决?最简单的一个方法就是使用引用计数(reference counting),仍是上面的那个例子,咱们给那块内存设一个引用计数,当内存被分配而且赋值给a时,引用计数是1。当把a赋值给b时引用计数增长到2。这时若是a再也不使用这块内存,它只须要把引用计数减1,代表本身再也不拥有这块内存。b再也不使用这块内存时也把引用计数减1。当引用计数变为0的时候,表明该内存再也不被任何指针所引用,系统能够把它直接释放掉。对象
3. 上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引发1中的问题,当数据为int, float等原生类型时,可使用assign。retain就如2中所述,使用了引用计数,retain引发引用计数加1, release引发引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。
4. copy是在你不但愿a和b共享一块内存时会使用到。a和b各自有本身的内存。
5. atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操做。在多线程环境下,原子操做是必要的,不然有可能引发错误的结果。加了atomic,setter函数会变成下面这样:
if (property != newValue) {
[property release];
property = [newValue retain];
}blog
关于retain,copy,assign的区别问题其实困扰我好久了,由于在程序中不太经常使用到copy,assign,因此三者的具体差异一直不太明白。
按照个人理解,assign和retain的区别,就是引入了一个计数器retaincount,就能够对一个内存的释放方便不少。copy,就是把原来的内存复制一遍,使各自都拥有一个内存,这样释放的时候也不会出错。
assign: 简单赋值,不更改索引计数(Reference Counting)。
copy: 创建一个索引计数为1的对象,而后释放旧对象
retain:释放旧的对象,将旧对象的值赋予输入对象,再提升输入对象的索引计数为1
使用assign: 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等)
使用copy: 对NSString
使用retain: 对其余NSObject和其子类
nonatomic,非原子性访问,不加同步,多线程并发访问会提升性能。注意,若是不加此属性,则默认是两个访问方法都为原子型事务访问
@property(nonatomic, retain) UITextField *userName编译时自动生成的代码
- (UITextField *) userName {
return userName;
}
- (void) setUserName:(UITextField *)userName_ {
[userName release];
userName = [userName_ retain];
}
@property(retain) UITextField *userName自动生成的代码
- (UITextField *) userName {
UITextField *retval = nil;
@synchronized(self) {
retval = [[userName retain] autorelease];
}
return retval;
}
- (void) setUserName:(UITextField *)userName_ {
@synchronized(self) {
[userName release];
userName = [userName_ retain];
}
}
摘自 青峰专栏