1.线程安全的: atomic, nonatomic
2.访问权限的: readonly, readwrite
3.内存管理(ARC) assign,strong,weak,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,不会产生野指针.
(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. 替换成自定义的函数