分享

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

 xiaotianyueye 2016-12-07




由于Swift 3.0 出了太多令人兴奋的新特性,人们很容易忽略 Objective-C中的小改动。或许你会觉得苹果提及Objective-C 很可能是为了提高和Swift互操作性(译者注:互操作性主要是指OC代码与Swift代码相互转换),不过苹果仍然很欢迎开发者用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)


翻译如下:

Objective-C 现在支持类属性了,与OC 中的类属性对应的是Swift的类型属性。

它们是这样声明的:@property (class) NSString *someStringProperty;
类属性永远不会被自动合成。


为了实践一下,我们来创建一个包含几个类型的简单 Objective-C 类。这是我们的 `User`类接口,它看起来是这样的:

@interface User : NSObject

@property (class, nonatomic, assign, readonly) NSInteger userCount;

@property (class, nonatomic, copy) NSUUID *identifier;

+ (void)resetIdentifier;

@end

下面来说明一下我们这两个类属性,第一个是只读的integer类型,第二个是可读可写具有copy特性的NSUUID类型。要注意有属性声明的类。


实现也很简单,我们首先需要存储 `identifier` 和 `userCount` 类属性。由于它们是类级别的也不是实例变量,因此我们把他们声明为静态的:

@implementation User

static NSUUID *_identifier = nil;

static NSInteger _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 = [super init];

  if (self) {

    _userCount += 1;

  }

  return self;

}


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

+ (void)resetIdentifier {

  _identifier = [[NSUUID alloc] init];

}

 

@end


我们可以在类名后使用点语法来获取到类属性:
User.userCount;
User.identifier;

这里有一个关于User类用法的例子:

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);


这是输出:

// 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 后的样子:

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


微信号:CocoaChinabbs

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多