OC中的属性Property和点语法
属性是什么
我们都知道,属性是变量和它对应的setter和getter方法的集合,是一种语法糖,是一种简化的写法。也就是说,当你声明了一个属性的时候,你同时声明了一个变量,一个setter方法,一个getter方法。
@property NSObject *property;
等价于
NSObject *_property;
- (void)setProperty:(NSObject *)property {
_property = property;
}
- (NSObject *)property {
return _property;
}
这次我们就来了解一下OC中属性的一些特性。
对比Swift中的属性类型
在Swift中,属性是有很多类型的,有存储属性、计算属性、延迟属性、可选属性、类属性等。
Swift是以OC为基础而设计的全新语言,它虽然有着全新的更全面的语法特性,但是依然能看出OC的影子。相反的,我们可以从Swift的对比中分析OC的一些特性。
存储属性
现在,我们声明一个字符串属性:
@property NSString *str;
这其实就是一个存储属性,因为他生成了一个变量用来存放字符串数据。
计算属性
那计算属性又是什么呢?
计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其他属性或变量的值。
根据上面的描述得出:就是没有生成变量,只有setter/getter方法的属性就是计算属性。其实在很早之前,定义属性的时候是不会生成变量的,需要使用 @synthesize str = _str;
这样的方式来生成变量,同时定义变量的名称。但在后来,Apple默认会生成变量。
那么在OC中,如何创建一个计算属性呢?
在OC中,有这样一条规则,如果声明的属性同时重写了setter方法和getter方法,需要使用 @synthesize
重新声明变量。也就是说,如果不声明变量,他就是一个有着setter/getter方法的计算属性。
那么如果只需要实现setter/getter方法中的其中一个的计算属性怎么办呢?这里就到了@dynamic
关键字登场了。
被@dynamic`修饰的属性在OC中被称为动态属性。顾名思义,就是用于动态计算的属性。
@synthesize
和@dynamic
都是定义在@implementation
下面的。
延迟属性
Swift中的延迟属性,在OC中的表现形式就是懒加载。
- (NSMutableArray *)dataSource {
if (!_dataSource) {
_dataSource = [[NSMutableArray alloc] init];
}
return _dataSource;
}
这是一个典型的懒加载模式,是通过重写getter方法来动态的初始化变量,但是这样的写法并不完全满足延迟属性,因为该方法已经无法获取到nil
这个值了。
可选属性
在Swift中,每个对象初始化的时候,所有的存储属性必须得到初始化,为了简化类的初始化,所以增添了可选型Optional。可选属性默认值为nil
。在OC中,所有定义的属性并没有强制初始化,所以都为可选属性。
类属性
类属性,顾名思义就是类自身的属性,他不属于对象,而是属于类本身。通过class
修饰符实现。
@property (class, readonly, strong) NSUserDefaults *standardUserDefaults;
@property (class, readonly, strong) NSFileManager *defaultManager;
@property (class, readonly, strong) NSNotificationCenter *defaultCenter;
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) UIPasteboard *generalPasteboard;
#else
+ (UIPasteboard *)generalPasteboard;
#endif
如今iOS框架中的单例方法都从一个单例方法逐步变成了现在的类属性的方式。
定义的类属性需要使用
@dynamic
修饰
点语法
点语法是跟随属性的应用而生的,是为了更加简单方便的访问属性而出的语法特性。而他本质上其实是一个动态方法,它无关乎是否是属性,它只是转换成对应setter/getter方法格式的参数来调用方法而已。
如下两个方法也可以使用点语法来调用,就是这个道理。
- (id)copy;
- (id)mutableCopy;