在OC中使用 class 属性修饰符

本篇为翻译稿,原文链接:Objective-C Class Properties

随着所有关于新的Swift 3语言功能的兴奋,很容易忽略Objective-C仍然发生的一些小改进。 虽然现在苹果做了很多从 Objective-C转向Swift工作,但是这些小改变对于需要使用Objective-C来开发的人来说,仍然受到欢迎。

在这篇文章中,我们来看看给Objective-C 类的成员变量添加 class 属性。

Objective-C Class Properties

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现在支持与Swift类型属性进行交互转换的类属性,这些属性永远不会synthesized

让我们进行如下的一个实验,我们创建一个具有类属性的Objective-C类:User;如下:

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

为了说明的目的,我有两个属性,第一个是只读整数,第二个是可复制的带读写属性NSUUID类。 注意属性声明中的class属性。

实现很简单,首先我们需要存储identifier和userCount类属性。 由于这些是 class 级别而不是实例变量,我们将它们声明为静态的:

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

现在我们为这两个类属性创建setter和getter方法;就像上面引用的苹果的文档一样,这两个属性永远不会synthesized,因此如果我们不显示添加setter和getter方法,XCode就会提示警告信息使用@dynamic或者是提供setter和getter方法; 首先,只读userCount属性只需要一个getter,它只返回计数的值。 注意在getter方法前面使用 + 让其成为一个类的方法:

+ (NSInteger)userCount {
  return _userCount;
}

identifier 属性需要一个setter和一个getter方法;在getter方法中如果改属性为nil,我们就创建一个identifier,如下:

+ (NSUUID *)identifier {
  if (_identifier == nil) {
    _identifier = [[NSUUID alloc] init];
  }
  return _identifier;
}

+ (void)setIdentifier:(NSUUID *)newIdentifier {
  if (newIdentifier != _identifier) {
    _identifier = [newIdentifier copy];
  }
}

同时我们创建一个基本的初始化方法,在这个初始化方法里我们将更新userCount属性;

- (instancetype)init
{
  self = [super init];
  if (self) {
    _userCount += 1;
  }
  return self;
}

+ (void)resetIdentifier是一个方便用来创建新的identifier的方法;

+ (void)resetIdentifier {
  _identifier = [[NSUUID alloc] init];
}

@end

您可以使用类名上的普通点语法访问类属性:

User.userCount;
User.identifier;

用法如下示例:

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的环境下使用

Generated Swift interface

似乎Objective-C获得的唯一增强功能是提高与Swift的互通性。 向Objective-C添加 class 属性映射到Swift中使用类变量。 这是为我们的User类生成的Swift代码:

public class User : NSObject { 
  public class var userCount: Int { get }
  public class var identifier: UUID!   
  public class func resetIdentifier()
}

请注意,我们的identifier属性是一个隐式拆包可选意思,我们从来没有希望它为零。 为了允许它为零,我们需要在Objective-C属性声明中添加一个nullable的声明,这样Swift变量将是一个可选的。 有关更多详细信息,请参阅Using nullable to annotate Objective-C

Further Reading

WWDC 2016 Session 405 What’s New in LLVM

    原文作者:AppleTTT
    原文地址: https://www.jianshu.com/p/d49e08cf36fe
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞