引言

Swift,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序。Swift吸收了众多现代编程语言的优点,尽力的提供简洁的编程语言和强大的功能。

WWDC 2017 给大家带来了很多惊喜。Swift 4 也伴随着 Xcode 9 测试版来到了我们的面前,很多强大的新特性非常值得我们期待在正式项目中去使用它。因为 Swift 4 是开源的,如果你关注 swift-evolution 这个项目的话,就应该已经提前了解到它的新特性了。本文参考了 WWDC 2017 以及各种资料,,从语法、字符串、标准库、构建过程等方面,把 Swift 4 的这些新特性一一列举出来做介绍和分析,让他们毫无保留地展现在你眼前,下面话不多说了,来随着小编一起看看详细的介绍吧。

一、语法改进

extension 中可以访问 private 的属性

考虑以下代码:

struct Date: Equatable, Comparable {

private let secondsSinceReferenceDate: Double

static func ==(lhs: Date, rhs: Date) -> Bool {

return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate

}

static func Bool {

return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate

}

}

上面代码定义了一个 Date 结构体,并实现 Equatable 和 Comparable 协议。为了让代码更清晰,可读性更好,一般会把对协议的实现放在单独的 extension 中,这也是一种非常符合 Swift 风格的写法,如下:

struct Date {

private let secondsSinceReferenceDate: Double

}

extension Date: Equatable {

static func ==(lhs: Date, rhs: Date) -> Bool {

return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate

}

}

extension Date: Comparable {

static func Bool {

return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate

}

}

但是在 Swift 3 中,编译就报错了,因为 extension 中无法获取到 secondsSinceReferenceDate 属性,因为它是 private 的。于是在 Swift 3 中,必须把 private 改为 fileprivate。

struct Date {

fileprivate let secondsSinceReferenceDate: Double

}

...

但是如果用 fileprivate,属性的作用域就会比我们需要的更大,可能会不小心造成属性的滥用。

在 Swift 4 中,private 的属性的作用域扩大到了 extension 中,并且被限定在了 struct 和 extension 内部,这样就不需要再改成 fileprivate 了,这是最好的结果。

类型和协议的组合类型

考虑以下代码:

protocol Shakeable {

func shake()

}

extension UIButton: Shakeable { /* ... */ }

extension UISlider: Shakeable { /* ... */ }

func shakeEm(controls: [???]) {

for control in controls where control.state.isEnabled {

}

control.shake()

}

在 Swift 3 中,这里的 ??? 应该写什么呢?如果写 UIControl,那么 control.shake() 就会报错;如果写 Shakeable,那么 control.state.isEnabled 就会报错。其实我们也可以这样写:

func shakeEm(controls: [UIControl]) {

for control in controls where control.isEnabled {

if control is Shakeable {

(control as! Shakeable).shake()

}

}

}

这样写虽然可以跑通了,但是很丑陋。

在 Swift 4 中,可以把类型和协议用 & 组合在一起作为一个类型使用,就可以像下面这样写了:

protocol Shakeable {

func shake()

}

extension UIButton: Shakeable { /* ... */ }

extension UISlider: Shakeable { /* ... */ }

func shakeEm(controls: [UIControl & Shakeable]) {

for control in controls where control.state.isEnabled {

control.shake()

}// Objective-C API

@interface NSCandidateListTouchBarItem : NSTouchBarItem

@property (nullable, weak) NSView *client;

@end

}

把它声明为了 UIControl & Shakeable 类型。OK,圆满解决。

PS:

这个代码例子是 WWDC 2017 的 PPT 中的,上面的代码有点问题,control.state.isEnabled 这句代码中,state 是没有 isEnabled 这个属性的,改为 control.isEnabled 就可以了。看来苹果的工程师做 PPT 有时候还是不太严谨。

另外,iOS SDK 中的 API 也用这个特性做了优化,例如:

// Objective-C API

@interface NSCandidateListTouchBarItem : NSTouchBarItem

@property (nullable, weak) NSView *client;

@end

这个 API 的 Objective-C 版本是没有问题的,可以知道 client 属性既是一个 NSView,又符合 NSTextInputClient 协议。然而它对应的 Swift 3 版本为:

class NSCandidateListTouchBarItem : NSTouchBarItem {

var client: NSView?

}

仅仅是一个 NSView 类型 /(ㄒoㄒ)/~~

在 Swift 4 中,这类 API 做了优化,改成了:

class NSCandidateListTouchBarItem : NSTouchBarItem {

var client: (NSView & NSTextInputClient)?

}

这样类型的声明就更加严谨了。

Associated Type 可以追加 Where 约束语句

在 Swift 4 中可以在 associatedtype 后面声明的类型后追加 where 语句

associatedtype Element where

看下面是 Swift 4 标准库中 Sequence 中 Element 的声明:

protocol Sequence {

associatedtype Element where Self.Element == Self.Iterator.Element

// ...

}

它限定了 Sequence 中 Element 这个类型必须和 Iterator.Element 的类型一致。

通过 where 语句可以对类型添加更多的约束,使其更严谨,避免在使用这个类型时做多余的类型判断。

新的 Key Paths 语法

先来看看 Swift 3 中 Key Paths 的写法:

@objcMembers class Kid: NSObject {

dynamic var nickname: String = ""

dynamic var age: Double = 0.0

dynamic var friends: [Kid] = []

}

var ben = Kid(nickname: "Benji", age: 5.5)

let kidsNameKeyPath = #keyPath(Kid.nickname)

let name = ben.valueForKeyPath(kidsNameKeyPath)

ben.setValue("Ben", forKeyPath: kidsNameKeyPath)

Swift 4 中创建一个 KeyPath 用 `` 作为开头:

\Kid.nickname

当编译器可以推导出类型时,可以省略基础类型部分:

\.nickname

上面的代码在 Swift 4 中就可以这样写:

struct Kid {

var nickname: String = ""

var age: Double = 0.0

var friends: [Kid] = []

}

var ben = Kid(nickname: "Benji", age: 8, friends: [])

let name = ben[keyPath: \Kid.nickname]

ben[keyPath: \Kid.nickname] = "BigBen"

相比 Swift 3,Swift 4 的 Key Paths 具有以下优势:

类型可以定义为 class、struct

定义类型时无需加上 @objcMembers、dynamic 等关键字

性能更好

类型安全和类型推断,例如 ben.valueForKeyPath(kidsNameKeyPath) 返回的类型是 Any,ben[keyPath: \Kid.nickname] 直接返回 String 类型

可以在所有值类型上使用

下标支持泛型

有时候会写一些数据容器,Swift 支持通过下标来读写容器中的数据,但是如果容器类中的数据类型定义为泛型,以前的下标语法就只能返回 Any,在取出值后需要用 as? 来转换类型。Swift 4 定义下标也可以使用泛型了。

struct GenericDictionary {

private var data: [Key: Value]

init(data: [Key: Value]) {

self.data = data

}

subscript(key: Key) -> T? {

return data[key] as? T

}

}

let dictionary = GenericDictionary(data: ["Name": "Xiaoming"])

let name: String? = dictionary["Name"] // 不需要再写 as? String

二、字符串

Unicode 字符串在计算 count 时的正确性改善

在 Unicode 中,有些字符是由几个其它字符组成的,比如 é 这个字符,它可以用 \u{E9} 来表示,也可以用 e 字符和上面一撇字符组合在一起表示 \u{65}\u{301}。

考虑以下代码:

var family = "

naarray查询 swift_Swift 4最全的新特性详细解析(推荐)相关推荐

  1. jdk1.5-1.7新特性详细介绍

    jdk1.5新特性 1.泛型 2.foreach 3.自动拆箱装箱 4.枚举 5.静态导入(Static import) 6.元数据(Metadata) 7.线程池 8.Java Generics  ...

  2. jdk1.5、1.6、1.7新特性详细介绍(整理)

    jdk1.5新特性 1.泛型 2.foreach 3.自动拆箱装箱 4.枚举 5.静态导入(Static import) 6.元数据(Metadata) 7.线程池 8.Java Generics 让 ...

  3. JDK7新特性详细说明及代码示例

    在2011年7月28日,Oracle发布了JDK7的正式版.最近我从网上搜集了一些资料,把文字说明和代码示例结合起来,方便我们的学习. 下面我们来看看JDK7比6多了哪些新特性 1.访问文件系统 与之 ...

  4. 前端HTML5十大新特性详细总结

    前端HTML5十大新特性总结 一 必须知道 写前端的都知道,在代码最前面都有这一行代码,大家都知道一定要把这东西写上去. <!DOCTYPE html> 但是!这是什么玩意儿?为什么要写上 ...

  5. mysql通配符查询 性能_使用mysql5.7新特性解决前通配符查询性能问题

    众所周知,在mysql里的后通配符可以使用索引查找,前通配查询却无法使用到索引,即使是使用到了索引,也是使用了索引全扫描,效率依然不高,再MySQL5.7之前,一直都没有好的办法解决,但是到了MySQ ...

  6. CSS3新特性详细介绍

    文章内容持续更新中~ 文章目录 一.CSS3实现圆角 - border-radius 二.盒子阴影 - box-shadow 三.文本阴影 - text-shadow 四.渐变 - gradient ...

  7. .NET Core 3.0 正式公布:新特性详细解读

    点击蓝字"dotNET匠人"关注我哟 加个"星标★",每日 7:15,好文必达! 作者丨Richard Lander 译者丨核子可乐 策划丨赵钰莹 近日,.NE ...

  8. upload-labs 全1-21关 附详细解析(文件上传漏洞)

    目录 注释:分析在每关开头. 第 1 关 第 2 关 第 3 关 第 4 关​​​ 第 5 关 第 6 关​​​ 第 7 关 第 8 关 第 9 关​ 第 10 关 第 11 关 ​第 12 关 第 ...

  9. H5的新特性(详细汇总)

    1. 拖拽释放(Drapanddrop)APIondrop 拖放是一种常见的特性, 即抓取对象以后拖到另一个位置 在HTML5中, 拖放是标准的一部分, 任何元素都能够拖放 2. 自定义属性data- ...

最新文章

  1. linux lisp环境,Ubuntu下Common Lisp配置
  2. python网络安全怎么学_学习网络安全包住宿
  3. Oracle-数据泵expdp/impdp实操
  4. C语言中时间的基本用法
  5. selenium的使用教程1
  6. 使用Object.observe 实现数据绑定
  7. flask post json_【python:flask-SocketIO】网络通信框架简单了解
  8. 响应式设计(Response Web Design)浅谈
  9. 余承东:华为Mate 30 RS保时捷设计 9月19日发布
  10. 使用CCDirector的notificationNode来创建独立的信息提示层
  11. 事业单位非编制值得去吗?
  12. 页面显示正常,控制台报错
  13. paip.c++ qt 网页爬虫 的 网络编程 总结
  14. 高分3号介绍及PIE使用
  15. PPT中放射发散型的文字效果设计技巧
  16. 北京16个山水美景| 清明小长假走起吧!
  17. 民生服务是“双创”永恒主题 且听“鸿雁旅居网”、“熊猫中医”谈背后心路历程...
  18. C语言自学笔记,第一天
  19. Java大作业之餐厅管理系统
  20. CentOS中 DNF 和 Yum 的区别

热门文章

  1. Leet Code OJ 14. Longest Common Prefix [Difficulty: Easy]
  2. 27行代码AC_迷宫 2017年第八届蓝桥杯A组第一题(暴力、仿迷宫)
  3. 简洁明了——STL容器库之set头文件常用函数集合
  4. [leetcode]541.反转字符串||
  5. Xcode搭建真机调试环境 图文实例
  6. python 服务器_只要一行Python代码,就能搭建一个共享文件局域网服务器
  7. python的进阶之路_Python 从入门到进阶之路(三)
  8. 计算机联网实验步骤,计算机网络技术实验操作过程.doc
  9. python创建按钮_掌握Python之Tkinter按钮组件的创建及使用
  10. 锐起无盘服务器安装教程,锐起无盘安装方法 图文教程