--参考:(iOS中属性与成员变量的区别)http://www.cnblogs.com/crazypebble/p/3439261.html
------------早期GCC版本------------
--@property A作用就是让编译器在h文件声明A 的setter/getter方法;
--@synthesize A作用就是让编译器在m文件生成A 的setter/getter方法;(如果自己实现了setter/getter方法,则以自己实现为准)
--要求必须要成员变量A 对应属性;或者将名称不一样成员变量_A对应属性A,即@synthesize A = _A;
--另外,属性的retain、assign、copy等修饰词就是在setter方法里retain/release等额外操作;
------------现在LLVM版本------------
--@property A作用强大了,除了原有作用;同时还Default synthesis of @property instance variables and accessor methods;具体:
1..如果发现m中没有@synthesize,则"Autosynthesized A= _A"(补上synthesize和匹配的_A);有@synthesize,不做处理;
2.根据m中@synthesize中匹配的实例变量查看有没有,若没有创建之。(@synthesize A匹配的实例变量为A;@synthesize A = _A 匹配的实例变量为_A)
--上叙俩规则根据例子总结,未找到相关文档说明:
--例子1;只有@property A ;那么m中 _A 能用,A 不能用;
--例子2;有@property A + 成员变量A; 那么 _A 能用,A能用;
--例子2: 有@property A + @synthesize A;那么 _A 不能,A 能用;
--例子3;有@property A + @synthesize A + 成员变量_A;那么 _A 能用,A 都能用;
--例子4;有@property A + @synthesize A=_A + 成员变量_A; 那么 _A 能用,A 不能用;
--一个经典例子,类中有属性@property(nonatomic,strong)IBOutlet UIButton *aButton; 和成员变量IBOutlet UIButton *_aButton; 没有@synthesize;他俩分别关联button1,和button2,运行程序,不管是self.aButton 还是_aButton都是指向button1;说明@property在编译的时候起作用,将_aButton 和属性aButton关联为一个。如果属性和成员变量是一样的,则一个关联button1,另一个也关联了。
------------类别中的属性property ------------
--类与类别中添加的属性要区分开来,因为类别中只能添加方法,不能添加实例变量。经常会在ios的代码中看到在类别中添加属性,这种情况下,是不会自动生成实例变量的。例:UINavigationController.h中会对UIViewController类进行扩展
@interface UIViewController (UINavigationControllerItem) @property(nonatomic,readonly,retain) UINavigationItem *navigationItem; @property(nonatomic) BOOL hidesBottomBarWhenPushed; @property(nonatomic,readonly,retain) UINavigationController *navigationController; @end这里添加的属性,不会自动生成实例变量,这里添加的属性其实是添加的getter与setter方法。
注意一点,匿名类别(匿名扩展)是可以添加实例变量的,非匿名类别是不能添加实例变量的,只能添加方法,或者属性(其实也是方法)
============修饰词============
主要分为三类:
1.原子性(Atomicity)包含:nonatomic;
2.读写属性(Writability)包含:readwrite / readonly;
3.setter语义(Setter Semantics)包含:assign / retain / copy;
------原子性:
nonatomic:非原子性访问,不加同步,多线程并发访问会提高性能。如果不加此属性,则默认是两个访问方法都为原子型事务访问。默认值是atomic,为原子操作。(atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。)
------读写属性:
readwrite / readonly:决定是否生成set访问器,readwrite是默认属性,生成getter和setter方法;readonly只生成getter方法,不生成setter方法。readonly关键字代表setter不会被生成, 所以它不可以和 copy/retain/assign组合使用。
注意:readwrite/readonly配合使用:属性在外部是只读,自己使用时读写-->re-declare the property in a class extension
@property(nonatomic,readonly)NSString *myName; //在.h 中 self.myName = @"ss"; 不能用;而 _myName = @"ss" 能用 //在.m中 //re-declare the property in a class extension @interface ViewController () @property(nonatomic,readwrite)NSString *myName; @end self.myName = @"ss"; 和 _myName = @"ss" 都能用
------setter语义:
很多Objective-C中的object最好使用用retain,一些特别的object(例如:string)使用copy。
============自定义setter/getter方法============
// 1,当把语义特性声明为assign时,setter和getter时方法内部实现 - (void)setName:(NSString *)name{ _name = name; } - (NSString *)name{ return _name; } //2,当把语义特性声明为retain时,setter和getter方法内部实现 - (void)setName:(NSString *)name{ if (_name != name) { [ _name release]; _name = [name retain]; } } - (NSString *)name{ return [[ _name retain] autorelease]; } //3,当把语义特性声明为copy时,setter和getter方法内部实现 - (void)setName:(NSString *)name{ if (_name != name) { [ _name release]; _name = [name copy]; } } - (NSString *)name{ return [[ _name retain] autorelease]; }注意自定setter方法的书写, 以前为了“安全”都在releae后面赋了一个nil的值。这样写是错误的,尤其对于retain的语音,因为有可能别的对象retain的它持有的对象,结果值被置为nil了。另不用担心初始的时候_name 就release了一次,因为类的成员中对象的初始值都是nil。
if (_name != name) { [ _name release]; _name = nil; _name = [name retain]; } }