由于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`类接口,它看起来是这样的:

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` 类属性。由于它们是类级别的也不是实例变量,因此我们把他们声明为静态的:

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

现在我们必须为这两个属性创建 `getter` 和 `setter` 方法。在正式版说明里已经提到过,这些类属性永远不会被合成,所以如果 缺少 `getter` 或 `setter`,Xcode 将会报警告。第一个只读的`userCount`仅需要一个返回count 值的 getter 方法。 注意使用 `+`使我们的getter 方法变成一个类方法:

1
2
3
+ (NSInteger)userCount {
  return _userCount;
}

`identifier` 属性则 getter方法 和 setter 方法都需要。在getter 方法中,如果identifier为空,我们就新建一个identifier:

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 的便利方法:

1
2
3
4
5
+ (void)resetIdentifier {
  _identifier = [[NSUUID alloc] init];
}
 
@end

我们可以在类名后使用点语法来获取到类属性:
User.userCount;
User.identifier;
这里有一个关于User类用法的例子:

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

Swift 3.0 令人兴奋,但Objective-C也有小改进--Objective-C的类属性的更多相关文章

  1. fir.im Weekly - Swift 3.0 的迁移适配指南

    无论你是移动开发者,还是桌面端开发者,或者正在IoT领域探索的技术人员,那么应该更加关注 iDev 全平台开发者大会,也许是后半年 iOS 开发者最盛大的技术盛宴.既有知名公司带来专业视野,又有从 S ...

  2. Swift 2.0初探

    转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心. 今年6月,一年一度的WWDC大会如期而至,在大会上Apple发布了Swift 2.0,引 ...

  3. iOS开发——新特性OC篇&Swift 2.0新特性

    Swift 2.0新特性     转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...

  4. Swift 2.0初探:值得注意的新特性

    转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度的WWDC大会如期而至,在大会上A ...

  5. Swift 3.0项目迁移的一些记录

    刚执行完Convert后报错600+,真是令人奔溃. 之后重新编译,仔细分析后发现其实真实错误远没有那么多.最终实际修改到的错误也就几十个,而且其中某些还是同一种错误. 这个项目是一个供自己使用的浏览 ...

  6. iOS开发系列--Swift 3.0

    概述 从写第一篇Swift文章的时候到现在Swift已经从1.2发展到了今天的3.0,这期间由于Swift目前还在发展阶段并不能向下兼容,因此第一篇文章中的部分代码在当前的Xcode环境中已经无法运行 ...

  7. Swift 3.0 【Swift 3.0 相较于 Swift 2.2 的变化】

    一.编译器和语法变化 函数或方法参数 调用函数或方法时从第一个参数开始就必须指定参数名 在Swift的历史版本中出现过在调用函数时不需要指定任何函数参数(或者从第二个参数开始指定参数名),在调用方法时 ...

  8. Swift 2.x -> Swift 3.0

    Swift 3.0 相对于 2.x 有很大变化.特别是因为命名习惯的改变,导致许多 Api 都发生了变化.总的趋势是让表示更简洁. 对旧的代码升级,大部分可以根据提示来进行更正.但也有的需要手动修改. ...

  9. Swift 2.0 异常处理

    转自:http://www.jianshu.com/p/96a7db3fde00 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主 ...

随机推荐

  1. 百度地图API示例之添加定位相关控件

    代码 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" cont ...

  2. 转:RealThinClient (RTC)是什么?

    RealThinClient SDK是用于开发标准的HTTP(S)服务器,ISAPI扩展以及客户端的VCL控件.可用于Windows下的CodeGear Delphi 6-XE5. 功能描述 Abou ...

  3. TCP协议总结--停止等待协议,连续ARQ协议,滑动窗口协议

    前言:在学习tcp三次握手的过程之中,由于一直无法解释tcpdump命令抓的包中seq和ack的含义,就将tcp协议往深入的了解了一下,了解到了几个协议,做一个小结. 先来看看我的问题: 这是用tcp ...

  4. 基于WDF的PCI/PCIe接口卡Windows驱动程序(4)- 驱动程序代码(源文件)

    原文出处:http://www.cnblogs.com/jacklu/p/4687325.html 本篇文章将对PCIe驱动程序的源文件代码作详细解释与说明.整个WDF驱动程序工程共包含4个头文件(已 ...

  5. 计算机网络 学习笔记-传输层:TCP协议简介

    概述: TCP传输前先要建立连接 TCP在传输层 点对点,一条TCP只能连接两个端点 可靠传输.无差错.不丢失.不重复.按顺序 全双工 字节流 TCP报文段 TCP报文段的报头前20字节是固定的,后面 ...

  6. 设置表格td宽度

      CSS布局,表格宽度不听使唤的实例.想把表格第一例宽度设为20,其他自适应.但CSS中宽度是等宽的.只设这一行也不起作用.但是在实际应用中总是等宽处理,并不按照样式来走. XML/HTML代码 & ...

  7. 《深入理解Nginx》阅读与实践(四):简单的HTTP过滤模块

    一.Nginx的HTTP过滤模块特征 一个请求可以被任意个HTTP模块处理: 在普通HTTP模块处理请求完毕并调用ngx_http_send_header()发送HTTP头部或调用ngx_http_o ...

  8. HTTP请求之:PHP函数header常用功能

    1.页面重定向   当浏览器接受到头信息中的 Location: http://xxxx 后,就会自动跳转到 http://xxxx 指向的URL地址,这点有点类似用 js 写跳转.但是这个跳转只有浏 ...

  9. 解决关于ArcGIS10.2服务手动启动的问题

    解决关于ArcGIS10.2服务手动启动的问题 C:\program files\arcgis\license10.2\bin> lmgrd -z -c service.txt新建一文本,将上面 ...

  10. table奇偶行设置颜色代码