因爲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