oc中的成员变量属性@synthesize和@dynamic理解

尽管已经写了一段时间的oc但对self.xxx和_xx的理解以及在三方代码中看到的@synthesize不是很理解,写代码还是不能太随便,不理解的东西写多了容易埋坑,所以还是花了点时间整理下这些到底是什么

什么是成员变量和属性

@interface Person : NSObject
{
    NSString *name ; // 成员变量,实例变量
}

// 属性
@property (nonatomic, strong) NSString *pName;
@end

定义在h文件中的属性和成员变量和m文件中定义的区别以及属性的特质相关内容不做讨论
一个博主的详细解析,以下大部分内容来自于此

@property的历史

iOS5之前,在苹果使用GCC编译器时候,属性的使用方式是:也就是手动声明实例变量,代码如下:

***.h***
@interface ViewController : UIViewController
{
    //属性的实例变量
    NSString *myTitle;
}
//编译器遇到@property会自动声明对应的setter/getter
@property (copy, nonatomic) NSString *myTitle;
@end

***.m***
// 编译器遇到@synthesize会自动实现setter/getter方法
// 编译器遇到@synthesize回去访问myTitle的同名变量,如果没找到就报错。
@synthesize myTitle;
iOS5之后,现在,苹果将默认编译器从 GCC转换为LLVM(low level virtual machine),从此 不再需要为属性声明实例变量 了。如果LLVM发现一个没有匹配实例变量的属性,它将**自动创建一个以下划线开头的实例变量**。因此,在这个版本中,我们不再为输出口声明实例变量。

同是也会自动添加@synthesize myTitle = _myTitle为自动生成的实例变量_myTitle创建setter/getter

@synthesize a = b,就是将a的getter/setter赋予b,b是实例变量,所以在操作self.a时实际是在操作_a变量

在ios5后即使@propety会自动生成_同名实例变量但当同时重写了属性的setter/getter以及使用了@dynamic xx又或是对一个readonly的属性重写了getter时都会导致_xx的实例属性不被自动生成,
另外如果使用@synthesize myTitle = _youname 使属性对应的实例变量改变时也不会自动生成_myTitle

@dynamic的作用

如果我们不想编译器给我们属性进行自动合成,由上面提到的自动生成例外中可以看出,如果使用了@dynamic a那么_a就不会存在

关于self.xx和_xx的区别

self.name 是对属性的访问,是调用的 name属性 的 getter/setter 方法;
_name 是对局部变量的访问,等价于 self->_name,并不会调用 getter/setter 方法;
OC中点表达式(.)其实就是调用对象的setter和getter方法的一种快捷方式。

那么使用哪种方式更好呢?

推荐使用 _XX 的理由:
原因一:《Effective OC2.0》中第7条:在对象内部尽量直接访问实例变量;
原因二:不进行OC方法派发,速度更快;

推荐使用 self.XX 的理由:
原因一:它可以兼容 懒加载;
原因二:避免了使用下划线的时候忽视了self这个指针,例如 self->_XX;
原因三:_XX 更容易造成循环引用;
原因四:使用 _XX 是获取不到父类的 属性,因为它只是对局部变量的访问;
原因五:self.XX 使用存在内存管理等优势,更加安全可靠。

上一篇:OC runtime


下一篇:Patch-based Output Space Adversarial Learning for Joint Optic Disc and Cup Segmentation