在使用@property定义property时可以在@property与类型之间用括号添加一些额外的指示符,常用的指示符有assign、atomic、copy、retain、strong、week、等。下面对它们的用途和常常对应的属性讲解一下。

  • assign:该指示符号对属性只是简单的赋值,不更改引用计数。常用于NSInteger等OC基础类型,以及short、int、double、结构体等C数据类型,因为这些类型不存在被内存回收的问题。

  • atomic、nonatomic:指定setter和getter是否是原子操作,即是否线程安全。如果是atomic,那么存取方法都是线程安全的,即某一线程访问存或者取方法,其他线程不可以进入该存、取方法。nonatomic则不具备线程安全的功能。需要指出的是atomic是默认值,可以保证数据的完整性,但是相应的降低了性能,所以在单线程环境中建议使用nonatomic来提升性能。

  • copy:如果使用copy指示符,当调用setter方法对成员变量赋值时,会将被赋值的对象复制的一个副本,再将该副本给成员变量,相应的原先的被赋值的对象的引用计数加1。当成员变量的类型是可变类型,或其子类是可变类型,被赋值的对象在赋值后有可能再被修改,如果不需要这种修改,则可以考虑copy指示符。

  • getter、setter:用于为getter方法、setter方法指定自定义方法名。比如getter=myName,setter=setName:,我们可以看到setter方法后面有一个(:),这是因为我们需要在后面添加参数。

  • readonly、readwrite:readonly指示系统只合成getter方法,不合成setter方法;readwrite是默认值,指示系统需要合成setter方法和getter方法。

  • retain:当把某个对象赋值给该属性时,该属性原来所引用的对象的引用计数减1,被赋值对象的引用计数加1。在未启用ARC机制的的情况下,retain可以保证一个对象的引用计数大于1时,该对象不会被回收。启用ARC后一般较少使用retain

  • strong、weak:strong指示符该属性对被赋值对象持有强引用,而weak指示符指定该属性对被赋值对象持有弱引用。强引用的意思是:只要该强引用指向被赋值的对象,那么该对象就不会自动回收。弱引用的意思是:即使该弱引用指向被赋值的对象,该对象也可能被回收。如果不希望对象被回收,可以使用strong指示符。如果需要保证程序性能,避免内存溢出,可以使用weak,内存一旦被回收,指针会被赋值为nil。

  • unsafe_unretained:与weak不同,被unsafe_unretained指针所引用的对象被回收后,unsafe_unretained指针不会被赋为nil,可能会导致程序出错。

1、atomic是默认行为,assign是默认行为,readwrite是默认行为

2、推荐做法是NSString用copy

3、delegate用assign(且一定要用assign)

4、非objc数据类型,比如int,float等基本数据类型用assign(默认就是assign)

5、其它objc类型,比如NSArray,NSDate用retain。


OC中提供了4个访问控制符:@private @package @protected @public。

@private(当前类访问权限):成员只能在当前类内部可以访问,在类实现部分定义的成员变量相当于默认使用了这种访问权限。

@package(同映像访问权限):成员可以在当前类或和当前类实现的同一映像中使用。同一映像就是编译后生成的同一框架或同一个执行文件。

@protected(子类访问权限):成员可以在当前类和当前类的子类中访问。在类接口部分定义的成员变量默认是这种访问权限。

@public(公共访问权限):成员可以在任意地方访问。


@private

@package

@protected

@public

同一个类中



同一个映像中





子类中





全局范围





下面使用@private来实现Person类,用来封装Person的2个属性,并将方法暴露出来:

[objc] view plain copy

 OC @property 指示符assign、atomic、copy、retain、strong、week、等_OC @property 指示符assiOC @property 指示符assign、atomic、copy、retain、strong、week、等_OC @property 指示符assi_02

  1. #import <Foundation/Foundation.h>  

  2. @interface Person : NSObject{  

  3.     //使用@private限制成员变量  

  4. @private  

  5.     NSString* _name;  

  6.     int _age;  

  7. }  

  8. //声明_name的set方法  

  9. -(void)setName:(NSString*)name;  

  10. //声明_name的get方法  

  11. -(NSString*)name;  

  12. //声明_age的set方法  

  13. -(void)setAge:(int)age;  

  14. //声明_age的get方法  

  15. -(int)age;  

  16. @end  

  17.   

  18.   

  19. #import "Person.h"  

  20. @implementation Person  

  21. //声明_name的set方法  

  22. -(void)setName:(NSString*)name{  

  23.     _name = name;  

  24. }  

  25. //声明_name的get方法  

  26. -(NSString*)name{  

  27.     return _name;  

  28. }  

  29. //声明_age的set方法  

  30. -(void)setAge:(int)age{  

  31.     _age = age;  

  32. }  

  33. //声明_age的get方法  

  34. -(int)age{  

  35.     return _age;  

  36. }  

  37. @end  

  38.   

  39. #import <Foundation/Foundation.h>  

  40. #import "Person.h"  

  41. int main(int argc, const charchar * argv[]) {  

  42.     @autoreleasepool {  

  43.         Person* person = [[Person alloc]init];  

  44.         //报错,age已经被封装起来,对外不可见  

  45.         //person->_age = 10;  

  46.         [person setAge:10];  

  47.         NSLog(@"age:%d",[person age]);  

  48.     }  

  49.     return 0;  

  50. }