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

EliseNoskow 5年前
   <p style="text-align:center"><img src="https://simg.open-open.com/show/fac9948f541d1c89c7bfd3d27f9afe06.jpg"></p>    <p>于Swift 3.0 出了太多令人兴奋的新特性,人们很容易忽略 Objective-C中的小改动。或许你会觉得苹果提及Objective-C 很可能是为了提高和Swift互操作性(译者注:互操作性主要是指OC代码与Swift代码相互转换),不过苹果仍然很欢迎开发者用Objective-C来完成工作。</p>    <p>在这篇文章中,我们就来看看Objective-C中新添加的类属性。</p>    <p><strong>Objective-C 类属性</strong></p>    <p>摘自 Xcode 8正式版中的说明:</p>    <p>Objective-C now supports class properties, which interoperate with Swift type properties. </p>    <p>They are declared as: @property (class) NSString *someStringProperty;. </p>    <p>翻译如下:</p>    <p>Objective-C 现在支持类属性了,与OC 中的类属性对应的是Swift的类型属性。</p>    <p>它们是这样声明的:@property (class) NSString *someStringProperty;</p>    <p>为了实践一下,我们来创建一个包含几个类型的简单 Objective-C 类。这是我们的 `User`类接口,它看起来是这样的:</p>    <pre>  <code class="language-objectivec">@interface User : NSObject  @property (class, nonatomic, assign, readonly) NSInteger userCount;  @property (class, nonatomic, copy) NSUUID *identifier;  + (void)resetIdentifier;  @end</code></pre>    <p>下面来说明一下我们这两个类属性,第一个是只读的integer类型,第二个是可读可写具有copy特性的NSUUID类型。要注意有属性声明的类。</p>    <p>实现也很简单,我们首先需要存储 `identifier` 和 `userCount` 类属性。由于它们是类级别的也不是实例变量,因此我们把他们声明为静态的:</p>    <pre>  <code class="language-objectivec">@implementation User  static NSUUID *_identifier = nil;  static NSInteger _userCount = 0;</code></pre>    <p>现在我们必须为这两个属性创建 `getter` 和 `setter` 方法。在正式版说明里已经提到过,这些类属性永远不会被合成,所以如果 缺少 `getter` 或 `setter`,Xcode 将会报警告。第一个只读的`userCount`仅需要一个返回count 值的 getter 方法。 注意使用 `+`使我们的getter 方法变成一个类方法:</p>    <pre>  <code class="language-objectivec">+ (NSInteger)userCount {    return _userCount;  }</code></pre>    <p>`identifier` 属性则 getter方法 和 setter 方法都需要。在getter 方法中,如果identifier为空,我们就新建一个identifier:</p>    <pre>  <code class="language-objectivec">+ (NSUUID *)identifier {    if (_identifier == nil) {      _identifier = [[NSUUID alloc] init];    }    return _identifier;  }    + (void)setIdentifier:(NSUUID *)newIdentifier {    if (newIdentifier != _identifier) {      _identifier = [newIdentifier copy];    }  }</code></pre>    <p>我们也为这个`User`类创建了一个会更新 count 属性的基本初始化方法。</p>    <pre>  <code class="language-objectivec">- (instancetype)init  {    self = [super init];    if (self) {      _userCount += 1;    }    return self;  }</code></pre>    <p>`resetIdentifier`类方法 是一个能创建一个新的identifier 的便利方法:</p>    <pre>  <code class="language-objectivec">+ (void)resetIdentifier {    _identifier = [[NSUUID alloc] init];  }    @end</code></pre>    <p>我们可以在类名后使用点语法来获取到类属性:</p>    <p>User.userCount;</p>    <p>User.identifier;</p>    <p>这里有一个关于User类用法的例子:</p>    <pre>  <code class="language-objectivec">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);</code></pre>    <p>这是输出:</p>    <pre>  <code class="language-objectivec">// 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</code></pre>    <p><strong>注意:</strong> 尽管这是Xcode 8 中 LLVM 编译器的新特性,但是它对于iOS 10之前的版本依然适用。</p>    <p><strong>生成的Swift接口</strong></p>    <p>似乎,Objective-C 最近的这些改进只是为了提高与Swift的互操作性。Objective-C中新添加的类型属性对应的是Swift中类变量的用法。下面这是我们 `User`类转换为 Swift 后的样子:</p>    <pre>  <code class="language-objectivec">public class User : NSObject {     public class var userCount: Int { get }    public class var identifier: UUID!       public class func resetIdentifier()  }</code></pre>    <p>注意,identifier 类属性是一个会隐式解包的变量,意味着我们永远也不希望它为nil。为了允许它为nil,我们需要在Objective-C的属性声明里添加一个 `nullable`的标识。 我们的Swift 变量也将会是可选类型的。</p>    <p> </p>    <p> </p>    <p>来自:http://www.cocoachina.com/ios/20161202/18257.html</p>    <p> </p>