Objective-C的@property、@synthesize和@dynamic
栏目: Objective-C · 发布时间: 5年前
内容简介:objc推荐我们通过set/get方法访问对象的属性。很显然,为每一个属性手动添加set/get方法的声明和实现是个性价比很低的重复劳动。因此,objc提供了一些关键字帮助我们简化这一过程。实际上就是这么回事儿。首先来看现在的property:例如:
objc推荐我们通过set/get方法访问对象的属性。很显然,为每一个属性手动添加set/get方法的声明和实现是个性价比很低的重复劳动。因此,objc提供了一些关键字帮助我们简化这一过程。实际上就是这么回事儿。
@property
首先来看现在的property:
例如:
@interface ViewController : UIViewController @property (nonatomic,assign) BOOL testVar; @end
简单理解,相当于声明了成员变量 _testVar
,声明了实现了set方法 setTestVar
、get方法 testVar
,等价于:
@interface ViewController : UIViewController { BOOL _testVar; } - (void)setTestVar:(BOOL)newTestVar; - (BOOL)testVar; @end @implementation ViewController - (void)setTestVar:(BOOL)newTestVar { _testVar = newTestVar; } - (BOOL)testVar { return _testVar; } @end
@synthesize
@synthesize可以指定set/get方法的实现。
1. 默认
默认地,@synthesize会生成一个同名的成员变量作为set/get的目标。
例如:
@interface ViewController : UIViewController @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar; @end
等价于:
@interface ViewController : UIViewController { BOOL testVar; } - (void)setTestVar:(BOOL)newTestVar; - (BOOL)testVar; @end @implementation ViewController - (void)setTestVar:(BOOL)newTestVar { testVar = newTestVar; } - (BOOL)testVar { return testVar; } @end
可以看到,set/get方法指向了成员变量 testVar
,也不会再默认生成 _testVar
。
注意,很多人误认为@synthesize默认生成的成员变量是 _testVar
,据我所知这是不对的。
官方文档 :
Important:If you use @synthesize
without specifying an instance variable name, like this:
@synthesize firstName;
the instance variable will bear the same name as the property.
In this example, the instance variable will also be called firstName
, without an underscore.
2. 指定
@synthesize也可以指定一个成员变量作为其set/get的目标。
例如:
@interface ViewController : UIViewController { BOOL exampleVar; } @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar = exampleVar; @end
等价于:
@interface ViewController : UIViewController { BOOL exampleVar; } - (void)setTestVar:(BOOL)newTestVar; - (BOOL)testVar; @end @implementation ViewController - (void)setTestVar:(BOOL)newTestVar { exampleVar = newTestVar; } - (BOOL)testVar { return exampleVar; } @end
此时set/get方法就指向了成员变量 exampleVar
。
特别的,可以声明并指定成员变量 _testVar
,例如:
@interface ViewController : UIViewController { BOOL _testVar; } @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar = _testVar; @end
这是最符合官方规范的做法:每个属性对应一个以 _
开头的成员变量。
可以看出,这种写法跟本文第一部分,只写一个 @property
的作用是一样的。
一点历史
其实,在xcode4.4(对应clang3.2/LLVM4.0)以前,显式声明 _testVar
和 @synthesize testVar = _testVar;
是标准做法。那时候只写个 @property
并不会给你带来成员变量和set/get的实现。
现在的表现是编译器把以前的标准做法化作默认行为的结果。当我们只声明了 @property
而没有实现对应的set/get方法时,编译器会默认声明 _
开头的成员变量并补全set/get的实现。
一个真实案例
最近遇到的问题是一坨老代码,里面用了 @synthesize
但是似乎不是很规范,后来维护的人看起来也不太熟悉这几个关键字,照着前人的代码瞎写,最后代码类似下面的:
@interface ViewController : UIViewController { BOOL _testVar; } @property (nonatomic,assign) BOOL testVar; @end @implementation ViewController @synthesize testVar; - (void)viewDidLoad { [super viewDidLoad]; self.testVar = YES; if(_testVar){ [self doSomething]; } } @end
可以看到,代码逻辑里用 _testVar
去做条件判断其实是完全无效的。
@dynamic
@dynamic的作用是告诉编译器,此属性对应的set/get方法将会被动态提供。
说得明白一点,其实@dynamic做了两件事:
- set/get我会自己提供的,不用帮我生成了
- 我会动态提供,没直接写在这里,编译器别给我报错
通常如果用到dynamic的话,这些方法会在消息转发的时候处理,也可以通过runtime的一些机制动态插入。 这里 有一些例子。
一般开发中基本上不会用到。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Linux设备驱动程序
科波特 / 魏永明、耿岳、钟书毅 / 中国电力出版社 / 2006-1-1 / 69.00元
本书是经典著作《Linux设备驱动程序》的第三版。如果您希望在Linux操作系统上支持计算机外部设备,或者在Linux上运行新的硬件,或者只是希望一般性地了解Linux内核的编程,就一定要阅读本书。本书描述了如何针对各种设备编写驱动程序,而在过去,这些内容仅仅以口头形式交流,或者零星出现在神秘的代码注释中。 本书的作者均是Linux社区的领导者。Jonathan Corbet虽不是专职的内核......一起来看看 《Linux设备驱动程序》 这本书的介绍吧!