Objective-C——retain/copy/assign/atomic/nonatomic/strong/weak/readonly/readwrite详解

版权声明:本文为博主原创文章,欢迎分享到其它技术社区,分享请标明出处: https://blog.csdn.net/CHENYUFENG1991/article/details/49685527

【atomic/nonatomic】

(1)atomic[默认属性]:OC使用的一种线程保护技术,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。

(2)nonatomic:非原子性访问,属性赋值的时候不加锁,多线程并发访问会提高性能。但可能会造成不安全。如果不加该属性,则默认setter/getter两个方法都是原子性事务访问。所以,atomic和nonatomic用来决定编译器生成的getter,setter是否为原子操作。



【assign/copy/retain】

(1)assign[默认值]:新建一个指向对象的指针(引用),但是不更改对象的引用计数,不考虑内存管理;常常用于基础数据类型(NSInteger)和C语言数据类型(int ,float,double,char等)。

(2)copy:建立一个引用计数为1的对象,原有对象不做改变;常常用于NSString。在赋值时传入值的一份拷贝,拷贝工作由copy方法执行。

(3)retain:   释放旧的对象,将旧对象的值赋给输入对象,再把输入对象的引用计数+1.  ;常常用于NSObject和其子类。需要对变量release,再retain新值。指定retain会在赋值时唤醒传入值的retain消息,此属性只能用于OC对象类型,而不能用于Core Foundation(retain会增加对象的引用计数,而基本数据类型或者Foundation对象都没有引用计数的概念)。

小结:assign和retain的区别,就是使用引用计数,可以对一个内存的释放方便很多。copy就是把原来的内存复制一遍,使各自都拥有一个内存,这样释放的时候也不会出错。


【copy和retain的区别】

copy是创建一个新对象。retain是创建一个指针,引用计数+1.

如:一个NSString对象,内存地址为:0x1111,内容为@“Hello”。

(1)copy到另外一个NSString后,地址为0x2222,内容相同(新建一个内容,内容拷贝),新的对象引用计数为1,旧的对象没有改变。

(2)retain到另外一个NSString后,地址相同(新建一个指针,指针拷贝),内容相同,对象的引用计数+1.


【assign和retain的区别】

(1)接触过C,那么假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b。此时a和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的。因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。

(2)知道了上述assign的问题,那么如何解决呢?最简单的一个方法就是使用引用计数。我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用计数是1。当把a赋值给b时,引用计数增加到2.这时如果a不再使用这块内存,他只需要引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数-1.当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以把它直接释放掉。

小结:assign就是直接赋值,从而可能引起1中的问题,当数据为int,float等原生类型时,可以使用assign。retain使用了引用计数,retain引起引用计数+1,release引起引用计数-1.当引用计数为0时,dealloc函数被调用,内存被回收。



【strong和weak】

(1)strong[默认值]:表明这是一个强引用。相当于retain属性。只要引用存在,对象就不能被销毁。当所有强引用消除时,对象才能被释放。

(2)weak:弱引用。相当于assign属性。一般为了避免retain cycles(就是父类中含有子类,父类retain了子类;子类中又调用了父类,子类又retain了父类),导致无法release,才会使用weak。

小结:strong和weak只有你在使用ARC的时候才能使用,此时你是不能使用retain,release,autorelease这些方法的,因为ARC会在必要的地方自动插入这些语句。所以我们需要在对象属性加上strong或者weak。



【readonly和readwrite】

这两个修饰很明显,readonly表示这个属性是只读不可修改的,readwrite(默认)表示属性是可读可写的。为了对某一个属性有较好的封装性,我们对同一个属性在.h文件中设置成readonly、在.m文件中设置成readwrite.如下所示:

头文件中:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property(nonatomic,copy,readonly) NSString *name;

@end


实现文件:

#import "ViewController.h"

@interface ViewController ()

@property(nonatomic,copy,readwrite) NSString *name;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

@end
这样我们就对同一个属性设置了较好的封装性。

       总结下,对于一个属性的4个默认的属性修饰是:atomic,readwrite,assign,strong。



github主页:https://github.com/chenyufeng1991  。欢迎大家访问!


展开阅读全文

没有更多推荐了,返回首页