• object-c中的assign,retain,copy,atomic,nonatomic,readonly,readwrite以及strong,weak


    assign:指定setter方法用简单的赋值,这是默认操作。你可以对标量类型(如int)使用这个属性。你可以想象一个float,它不是一个对象,所以它不能retain、copy。assign指定setter方法用简单的赋值,这是默认操作。
     

     retain:指定retain应该在后面的对象上调用,前一个值发送一条release消息。你可以想象一个NSString实例,它是一个对象,而且你可能想要retain它。retain释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 ,使用retain: 对其他NSObject和其子类 ,retain,是说明该属性在赋值的时候,先release之前的值,然后再赋新值给属性,引用再加1。

     

    copy:指定应该使用对象的副本(深度复制),前一个值发送一条release消息。基本上像retain,但是没有增加引用计数,是分配一块新的内存来放置它。

    readonly:将只生成getter方法而不生成setter方法(getter方法没有get前缀)。

     

    readwrite:默认属性,将生成不带额外参数的getter和setter方法(setter方法只有一个参数)。

     

    atomic:对于对象的默认属性,就是setter/getter生成的方法是一个原子操作。如果有多个线程同时调用setter的话,不会出现某一个线程执行setter全部语句之前,另一个线程开始执行setter的情况,相关于方法头尾加了锁一样。

     

    nonatomic:不保证setter/getter的原子性,多线程情况下数据可能会有问题。


    copy: 创建一个引用计数为1的对象,然后释放旧的对象

    retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的引用计数为 1

    Copy其实是建立了一个相同的对象,而retain不是:
    比如一个NSString对象,地址为0×1111,内容为@”STR”
    Copy到另外一个NSString之 后,地址为0×2222,内容相同,新的对象retain为1, 旧有对象没有变化

    retain到另外一个NSString之 后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1

    也就是说,retain是指针拷贝,copy是内容拷贝。在拷贝之前,都会释放旧的对象。

    1、使用copy: 对NSString

    2、使用retain: 对其他NSObject和其子类

    strong与weak是由ARC新引入的对象变量属性

    ARC引入了新的对象的新生命周期限定,即零弱引用。如果零弱引用指向的对象被deallocated的话,零弱引用的对象会被自动设置为nil。



    @property(strong) MyClass *myObject;

    相当于@property(retain) MyClass *myObject;

    @property(weak) MyOtherClass *delegate;

    相当于@property(assign) MyOtherClass *delegate;
    强引用与弱引用的广义区别:
    强引用也就是我们通常所讲的引用,其存亡直接决定了所指对象的存亡。如果不存在指向一个对象的引用,并且此对象不再显示列表中,则此对象会被从内存中释放。
    弱引用除了不决定对象的存亡外,其他与强引用相同。即使一个对象被持有无数个若引用,只要没有强引用指向他,那麽其还是会被清除。



    简单讲strong等同retain
    weak比assign多了一个功能,当对象消失后自动把指针变成nil,好处不言而喻。



    __weak, __strong 用来修饰变量,此外还有 __unsafe_unretained, __autoreleasing 都是用来修饰变量的。
    __strong 是缺省的关键词。
    __weak 声明了一个可以自动 nil 化的弱引用。
    __unsafe_unretained 声明一个弱应用,但是不会自动nil化,也就是说,如果所指向的内存区域被释放了,这个指针就是一个野指针了。
    __autoreleasing 用来修饰一个函数的参数,这个参数会在函数返回的时候被自动释放。

    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函数会变成下面这样:

    [cpp] view plaincopy
     
     
    1. <span style="font-size:14px;">if (property != newValue) {  
    2. [property release];  
    3. property = [newValue retain];  
    4. }</span>  
    [cpp] view plaincopy
     
     
    1.   

    关于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,非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问
    [cpp] view plaincopy
     
     
    1. @property(nonatomic, retain) UITextField *userName //编译时自动生成的代码  
    2. - (UITextField *) userName {  
    3. return userName;  
    4. }  
    5.   
    6. - (void) setUserName:(UITextField *)userName_ {  
    7. [userName release];  
    8. userName = [userName_ retain];  
    9. }  
    10.   
    11.   
    12. @property(retain) UITextField *userName //自动生成的代码  
    13.   
    14. - (UITextField *) userName {  
    15. UITextField *retval = nil;  
    16. @synchronized(self) {  
    17. retval = [[userName retain] autorelease];  
    18. }  
    19. return retval;  
    20. }  
    21.   
    22. - (void) setUserName:(UITextField *)userName_ {  
    23. @synchronized(self) {  
    24. [userName release];  
    25. userName = [userName_ retain];  
    26. }  
    27. }  
  • 相关阅读:
    uva10152-ShellSort
    WCF问题集锦:ReadResponse failed: The server did not return a complete response for this request.
    Android动态改变布局
    Android应用性能优化
    玩转CPU之直线
    [DB][MySql]关于取得自增字段的值、及@@IDENTITY 与并发性问题
    js对象实例化的常见三种方式
    TCP协议
    [UnityUI]循环滑动列表
    Spring MVC原理及实例基础扫盲篇
  • 原文地址:https://www.cnblogs.com/fuunnyy/p/4663122.html
Copyright © 2020-2023  润新知