@property中的修饰符

1.线程安全的: atomic, nonatomic 
2.访问权限的: readonly, readwrite 
3.内存管理(ARC) assign,strongweak,copy  (自动引用计数)
4.内存管理(MRC)assign, retain,copy  (手动引用计数)

5.指定方法名称: setter= getter=

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

nonatomic: 禁止多线程,变量保护,提高性能。

2.访问权限: 
readonly 表示只读, 也就是修饰的属性只有getter没有setter。 (只能读值,不能赋值)

readwrite 可读写, 也就是修饰的属性既有setter又有getter。   (只能赋值,不能读值)

3和4 我就要比较着来说了 
(1)Strong和 retain  
相同点
strong 和 retain 都是针对对象类型进行内存管理. 如果去修饰基本数据类型,Xcode会直接报错. 当给对象类型使用此修饰符时,setter方法会先将旧的对象属性release掉,再将新的对象赋值给属性并对该对象进行一次retain操作, 两者都会增加对象的引用计数

不同点:  
strong一般用于ARC环境, retain 用于MRC环境.

(2) assign 和 weak 

相同点:  
assign和weak不会牵扯到内存管理,不会增加引用计数 
不同点: 

assign 可修饰基本数据类型 也可修饰OC对象, 但如果修饰对象类型指向的是一个强指针, 当他指向的这个指针释放后, 他仍指向这块内存,必须手动给其置为nil, 否则就会产生野指针,如果还通过此指针操作那块内存,便会导致EXC_BAD_ACCESS错误,调用了已经释放的内存空间;

 而weak 只能修饰OC对象, 且相对assign比较安全, 如果指向的对象消失了,那么他会自动置为nil,不会产生野指针.

例子:

@interface ViewController ()


@property (nonatomic,weak)   NSDate *weakDate;

@property (nonatomic,assign) NSDate *assignDate;

@property (nonatomic,strong) NSDate *strongDate;

@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view.

    self.strongDate = [NSDate date];

    NSLog(@"strong属性:%@",self.strongDate);

    self.weakDate = self.strongDate;

    self.assignDate = self.strongDate;

    self.strongDate = nil;


    NSLog(@"weak属性:%@",self.weakDate);

   NSLog(@"assign属性:%@",self.assignDate); //报错Thread 1: EXC_BAD_ACCESS

}


打印:

 ASC[1049:131774] strong属性:2018-02-28 04:22:53 +0000

 ASC[1049:131774] weak属性:(null)

(3) copy、strong 和 可变、不可变类型

深拷贝 : 拷贝出来的对象与源对象地址不一致!这意味着我修改拷贝对象的值对源对象的值没有任何影响.(这是将指针和内容一起拷贝出来了并且成了一个全新的对象)
浅拷贝 : 拷贝出来的对象与源对象地址一致! 这意味着我修改拷贝对象的值会直接影响到源对象.(仅仅是拷贝了指针

附上简图一张,莫见笑,欢迎各位指正: 
这里写图片描述

1) copy 和 strong 都可修饰不可变类型,但一般用copy 

一般用copy修饰不可变的, 因为安全, 可以保证其封闭性. 
因为用copy修饰,setter方法中会自动判断如果来源,如果是不可变的,那和Strong一样,进行浅拷贝,会增加其引用计数,如果是可变的那么就深拷贝,不会增加其引用计数. 所以如果如果项目中这样的不可变对象(比如NSString)多的话,当一定数量if判断消耗的时间累加起来就会影响性能. 
所以,只需要记住一点,当你给你的不可变对象 赋值时, 如果来源是可变的,那么就用copy, 如果来源是不可变类型的,就用strong.

注:如果当strong修饰不可变的, 如果来源是不可变得,那么同上,没有问题. 如果来源是可变的时, 那么当源对象变化时,我们的不可变属性也会跟着变化,那么就破坏了其封闭性, 就不安全了.

2) 如果用 copy 修饰 可变类型 会出现什么问题? 
Copy 修饰 可变的对象的话, 会生成一个不可变的NSCFConstantSting对象,赋值给可变属性,编译没问题, 调方法修改其内容时崩溃. unrecognized selector sent to instance

总结 
1、copy 修饰 不可变的 要看赋值来源 
(1)来源是可变的话, 会自动进行深拷贝, 来源对象的变化不会影响我们的不可变属性 
(2)来源是不可变的话,那么就和strong一样大胆的指针拷贝,反正都不会改变. 
2、copy 修饰可变的. 
那么会生成一个不可变对象,赋值给可变属性,编译没问题,调方法修改其内容时会崩溃unrecognized selector sent to instance 
3、 Strong修饰不可变的 也要看来源 
(1)如果来源是不可变的, 那就没什么问题 
(2)如果来源是可变的, 那么当源对象的内容发生改变时,我们的不可变属性的值也会发生改变,那么就破坏的其封闭性, 不安全. 
4、strong修饰可变的 也要看来源 
(1)如果来源是不可变的, 那么会直接报警告运行出错 unrecognized selector sent to instance 
(2) 如果来源是可变的,那么没问题.

5 指定setter和getter , 就是不用系统getter 和 setter. 替换成自定义的函数




你可能感兴趣的:(@property中的修饰符)