一、修饰 @property 的特性类型:
1、assign:
(1)、一般用来修饰基本的数据类型(例:NSInteger,CGFloat,int,char等等);
(2)、引用计数:不会增加,属性释放后就没有了;
(3)、内存分配:栈上,由系统自动处理,不会造成野指针;
(4)、是否可以用它修饰对象类型呢?(比如:NSArray、NSDictionary等等)?
答:修饰是可以的,但是这样属性释放后会造成野指针,后续被其他对象引用时就会产生crash现象。
2、retain:
(1)、用来修饰对象(NSObject)类型(例:NSArray、NSDictionary等等);
(2)、引用计数:引用时+1,释放时-1,只有当引用计数为0时,就会被dealloc函数回收内存;
(3)、内存分配:堆上,(alloc,new),由编程者手动释放,但在ARC环境下由编译器自动检测管理,最后在引用计数为0时,就会被dealloc函数回收内存。
3、copy:
(1)、一般用来修饰NSString(NSMutableString),NSDictionary(NSMutableDictionary)等等(其对应有可变类型的子类),还有block;
(2)、引用计数:同retain;
(3)、内存分配:同retain;
(4)、与retain的区别:retain的引用是拷贝指针地址(浅拷贝),而copy是拷贝对象本身(深拷贝),重新分配地址;当修改对象值时,浅拷贝会改变原始值,而深拷贝不会。由于NSString与NSMutableString之间有可能进行赋值操作,为了防止内容被修改,因此使用copy去深拷贝一份。
4、weak:
(1)、即弱引用,类似于assign,一般用在防止循环引用的情景下(例:父类引用了子类,子类引用了父类);还用在IBOutlet、delegate(代理),由于它们会在类外部被调用,防止循环引用;
(2)、引用计数:不会增加,引用计数为0时,对象释放后自动置nil,不会造成野指针;
(3)、内存分配:堆上(对象申请内存地址都在堆上);
(4)、与assign的区别:当使用assign修饰对象的时,虽然引用计数不会增加,但是对象释放时会造成野指针,后续对象申请内存空间时,刚好使用当该内存地址就会造成crash异常,所以最好不要使用assign修饰对象。
5、strong:
(1)、即强引用,类似于retain,一般需要持有此对象的情景下(例:类内部的属性),若不是属性,则在初始化对象时,编译器会自动加上 __strong修饰;
(2)、引用计数:同retain,也会增加;
(3)、内存分配:堆上;
(4)、与retain的区别:一般情况下是一样的,但在修饰block的时是不一样的,strong会等价于copy;而retain居然等价于assign,内存分配在栈上,会造成野指针引起crash(BAD_ACCESS);因此,block最好使用copy修饰。
6、nonatomic:
(1)、即非原子性,不是默认的;更快;如有两个线程访问同一个属性,会出现无法预料的结果;非线程安全,适合内存较小的移动设备。
7、atomic:
(1)、即原子性,是默认的;对同一对象的set和get的操作是顺序执行的;速度不快,因为要保证操作整体完成;(读/写)线程安全,需要消耗大量系统资源来为属性加锁;系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响,而该属性在其他多个线程调用,并不保证线程安全,需要开发者自行处理。
8、readonly:
(1)、只读,只有get方法,不被外部改变时使用。
9、readwrite:
(1)、读写,有set、get方法。
注:属性没有显式修饰,则默认readwrite。
10、getter=XXX:
(1)、XXX表示get方法名;例:
@property (assign, nonatomic, getter=isDidSelected) BOOL didSelected;