美文网首页知识总结
在OC中使用 class 属性修饰符

在OC中使用 class 属性修饰符

作者: AppleTTT | 来源:发表于2017-06-09 11:47 被阅读616次

    本篇为翻译稿,原文链接: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

    相关文章

      网友评论

        本文标题:在OC中使用 class 属性修饰符

        本文链接:https://www.haomeiwen.com/subject/fpnxqxtx.html