Objective-C的@property、@synthesize和@dynamic

栏目: Objective-C · 发布时间: 4年前

内容简介: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做了两件事:

  1. set/get我会自己提供的,不用帮我生成了
  2. 我会动态提供,没直接写在这里,编译器别给我报错

通常如果用到dynamic的话,这些方法会在消息转发的时候处理,也可以通过runtime的一些机制动态插入。 这里 有一些例子。

一般开发中基本上不会用到。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

网络流

网络流

拉文德拉K.阿胡亚 托马斯L.马南提 詹姆斯B.沃林 / 机械工业出版社 / 2005-5 / 108.0

本书全面介绍了经典的和现代的网络流技术,包括综合的理论、算法与应用。主要内容包括:路径、树与周期,算法设计与分析,最大流与最小流算法,分派与匹配,最小生成树,拉格朗日松弛与网络优化等。书中包含大量练习题,拓展了本书的内容,便于教学。一起来看看 《网络流》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具