Swift 3.0 使人兴奋,但Objective-C也有小改进--Objective-C的类属性

因为Swift 3.0 出了太多使人兴奋的新特性,人们很容易忽略 Objective-C中的小改动。或许你会以为苹果说起Objective-C 极可能是为了提升和Swift互操做性(译者注:互操做性主要是指OC代码与Swift代码相互转换),不过苹果仍然很欢迎开发者用Objective-C来完成工做。objective-c

在这篇文章中,咱们就来看看Objective-C中新添加的类属性。
Objective-C 类属性
摘自 Xcode 8正式版中的说明:
Objective-C now supports class properties, which interoperate with Swift type properties. 
They are declared as: @property (class) NSString *someStringProperty;. 
They are never synthesized. (23891898)
翻译以下:app

Objective-C 如今支持类属性了,与OC 中的类属性对应的是Swift的类型属性。
它们是这样声明的:@property (class) NSString *someStringProperty;
类属性永远不会被自动合成。
为了实践一下,咱们来建立一个包含几个类型的简单 Objective-C 类。这是咱们的 `User`类接口,它看起来是这样的:ide

1
2
3
4
5
@interface User : NSObject
@property (class, nonatomic, assign, readonly) NSInteger userCount;
@property (class, nonatomic, copy) NSUUID *identifier;
+ (void)resetIdentifier;
@end

下面来讲明一下咱们这两个类属性,第一个是只读的integer类型,第二个是可读可写具备copy特性的NSUUID类型。要注意有属性声明的类。
实现也很简单,咱们首先须要存储 `identifier` 和 `userCount` 类属性。因为它们是类级别的也不是实例变量,所以咱们把他们声明为静态的:atom

1
2
3
@implementation User
static NSUUID *_identifier = nil;
static NSInteger _userCount = 0;

如今咱们必须为这两个属性建立 `getter` 和 `setter` 方法。在正式版说明里已经提到过,这些类属性永远不会被合成,因此若是 缺乏 `getter` 或 `setter`,Xcode 将会报警告。第一个只读的`userCount`仅须要一个返回count 值的 getter 方法。 注意使用 `+`使咱们的getter 方法变成一个类方法:url

1
2
3
+ (NSInteger)userCount {
   return  _userCount;
}

`identifier` 属性则 getter方法 和 setter 方法都须要。在getter 方法中,若是identifier为空,咱们就新建一个identifier:spa

1
2
3
4
5
6
7
8
9
10
11
12
+ (NSUUID *)identifier {
   if  (_identifier == nil) {
     _identifier = [[NSUUID alloc] init];
   }
   return  _identifier;
}
 
+ (void)setIdentifier:(NSUUID *)newIdentifier {
   if  (newIdentifier != _identifier) {
     _identifier = [newIdentifier copy];
   }
}

咱们也为这个`User`类建立了一个会更新 count 属性的基本初始化方法。翻译

1
2
3
4
5
6
7
8
- (instancetype)init
{
   self = [ super  init];
   if  (self) {
     _userCount += 1;
   }
   return  self;
}

`resetIdentifier`类方法 是一个能建立一个新的identifier 的便利方法:code

1
2
3
4
5
+ (void)resetIdentifier {
   _identifier = [[NSUUID alloc] init];
}
 
@end

咱们能够在类名后使用点语法来获取到类属性:
User.userCount;
User.identifier;
这里有一个关于User类用法的例子:blog

1
2
3
4
5
6
7
8
for  (int i = 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);

这是输出:接口

1
2
3
4
5
6
7
// 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 编译器的新特性,可是它对于iOS 10以前的版本依然适用。
生成的Swift接口
彷佛,Objective-C 最近的这些改进只是为了提升与Swift的互操做性。Objective-C中新添加的类型属性对应的是Swift中类变量的用法。下面这是咱们 `User`类转换为 Swift 后的样子:

1
2
3
4
5
public class User : NSObject { 
   public class  var  userCount: Int { get }
   public class  var  identifier: UUID!   
   public class func resetIdentifier()
}

注意,identifier 类属性是一个会隐式解包的变量,意味着咱们永远也不但愿它为nil。为了容许它为nil,咱们须要在Objective-C的属性声明里添加一个 `nullable`的标识。 咱们的Swift 变量也将会是可选类型的。看 [Using nullable to annotate Objective-C]能够看到更多详细内容。
拓展阅读
WWDC 2016 Session 405 What’s New in LLVM

相关文章
相关标签/搜索