由于Swift3.0 出了太多令人兴奋的新特性,人们很容易忽略Objective-C中的小改动。苹果展示Objective-C 很可能是为了提高Swift互操作性(译者注:互操作性主要是指OC代码与Swift代码相互转换),但是仍然很欢迎开发者用Objective-C来完成工作。
在这篇文章中,我们就来看看Objective-C中新添加的类属性。
摘自 Xcode 8正式版中的说明:
Objective-C now supportsclassproperties,whichinteroperatewithSwifttypeproperties.
They are declared as:@property(class) NSString *someStringProperty;.
They are never synthesized. (23891898)
Objective-C现在支持类属性了,与OC中的类属性对应的是Swift的类型属性。
它们是这样声明的:@property(class)NSString*someStringProperty;
类属性永远不会被自动合成。
为了实验一下,我们来创建一个包含几个类型的简单 Objective-C 类。这是我们的User类接口,它看起来是这样的:
@interfaceUser:NSObject
@property class,nonatomic,assign,readonly) NSInteger userCount;
@property (class,nonatomic, copy) NSUUID *identifier;
+ (void)resetIdentifier;
@end
下面来说明一下我们这两个类属性,第一个是只读的integer类型,第二个是可读可写具有copy特性的NSUUID类型。要注意有属性声明的类。
实现也很简单,我们首先需要存储identifier和userCount类属性。由于它们是类级别的也不是实例变量,因此我们把他们声明为静态的:
@implementation
UserstaticNSUUID *_identifier =nil;
staticNSInteger_userCount =0;
现在我们必须为这两个属性创建getter和setter方法。在正式版说明里已经提到过,这些类属性永远不会被合成,所以如果 缺少getter或setter,Xcode 将会报警告。第一个只读的userCount仅需要一个返回count 值的 getter 方法。 注意使用+使我们的getter 方法变成一个类方法:
+ (NSInteger)userCount {return_userCount;}
identifier属性则 getter方法 和 setter 方法都需要。在getter 方法中,如果identifier为空,我们就新建一个identifier:
+ (NSUUID *)identifier {
if(_identifier ==nil) {
_identifier = [[NSUUID alloc] init];
}
return_identifier;
}
+ (void)setIdentifier:(NSUUID *)newIdentifier {
if(newIdentifier != _identifier) {
_identifier = [newIdentifier copy];
}
}
我们也为这个User类创建了一个会更新 count 属性的基本初始化方法。
- (instancetype)init{
self= [superinit];
if(self) {
_userCount +=1;
}returnself;
}
resetIdentifier类方法 是一个能创建一个新的identifier 的便利方法:
+ (void)resetIdentifier {
_identifier = [[NSUUID alloc] init];
}
@end
我们可以在类名后使用点语法来获取到类属性:
User.userCount;User.identifier;
这里有一个关于User类用法的例子:
for(inti =0; i <3; i++) {self.user= [[User alloc] init];NSLog(@"User count: %ld",(long)User.userCount);NSLog(@"Identifier = %@",User.identifier);}[User resetIdentifier];NSLog(@"Identifier = %@",User.identifier);
这是输出:
// User count: 1// Identifier = 4B98B7FD-F8DC-484A-92B2-B2BB20BCB709// User count: 2// Identifier = 4B98B7FD-F8DC-484A-92B2-B2BB20BCB709// User count: 3// Identifier = 4B98B7FD-F8DC-484A-92B2-B2BB20BCB709// Identifier = A0519681-1E08-4DF2-B2D1-D077CF2BDEFF
注意
尽管这是Xcode 8 中 LLVM 编译器的新特性,但是它对于iOS10之前的版本依然适用。
似乎,Objective-C 最近的这些改进只是为了提高与Swift的互操作性。Objective-C中新添加的类型属性对应的是Swift中类变量的用法。下面这是我们User类转换为 Swift 后的样子:
publicclassUser : NSObject {
publicclassvaruserCount: Int {get}publicclassvaridentifier: UUID!publicclassfuncresetIdentifier()
}
注意,identifier 类属性是一个会隐式解包的变量,意味着我们永远也不希望它为nil。为了允许它为nil,我们需要在Objective-C的属性声明里添加一个nullable的标识。 我们的Swift 变量也将会是可选类型的。看Using nullable to annotate Objective-C可以看到更多详细内容。