---
layout:     post
title:      Swift 4 新特性
subtitle:   很高兴 Swift 4 不再是一门新语言了😅
date:       2017-09-11
author:     BY
header-img: img/post-bg-ios10.jpg
catalog: true
tags:
    - iOS
    - Swift
---


### private 权限扩大

在 Swift 4 中，`extension` 可以读取 `private` 变量了。

Swift 3 中，如果将主体函数的变量定义为 `private`，则其 `extension` 无法读取此变量，必须将其改为 `filePrivate` 才可以。

### 单向区间

单向区间是一个新的类型，主要分两种：确定上限和确定下限的区间。直接用字面量定义大概可以写成 `…6`和 `2…`

例如

```swift
let intArr = [0, 1, 2, 3, 4]

let arr1 = intArr[...3] 	// [0, 1, 2, 3]
let arr2 = intArr[3...] 	// [3, 4]
```

### 字符串改动


#### String 操作简化了

`String` 许多要通过 `.characters` 进行的操作，可以直接用 String 进行操作了。

例如：

```swift
let greeting = "Hello, 😜!"
// No need to drill down to .characters
let n = greeting.count
let endOfSentence = greeting.index(of: "!")!

```

#### 新增 Substring 类型


swift 4 为字符串片段新增了一个叫 `Substring` 的类型。

当你创建一个字符串的片段时，会产生一个 `Substring` 实例。`Substring` 与 `String` 用法相同， 因为子串和原字符串共享内存，所以对子串的操作快速而且高效。

```swift
let greeting = "Hi there! It's nice to meet you! 👋"
let endOfSentence = greeting.index(of: "!")! 

// 产生 Substring 实例
let firstSentence = greeting[...endOfSentence]
// firstSentence == "Hi there!"

// `Substring` 与 `String` 用法相同
let shoutingSentence = firstSentence.uppercased()
// shoutingSentence == "HI THERE!" 
```

但是要注意一个 `Substring` 保留从其生成的完整的 `String`值。 当您传递一个看似很小的 `Substring` 时，这可能导致意外的高内存开销。所以使用 `Substring`时，最好转化为 `String`.

```swift
let newString = String(substring)
```


#### 换行可以不用 `\n`了！

Swift 3，字符串换行要插入 `\n`。
例如：

![](https://ws4.sinaimg.cn/large/006tNc79gy1fjdam0wvhhj305d0283yf.jpg)

在 Swift 4 可以这样操作:

![](https://ws2.sinaimg.cn/large/006tNc79gy1fjdas2yri4j303q0260sm.jpg)

用两个 `“”“` 包裹起来的字符串会自动添加 `\n` 换行，更加直观了。注意：换行与缩进参照的是第二个 `“”“` 号的位置。

嗯，我觉得OK！

#### 支持 Unicode 9

Swift 4 支持 Unicode 9，[为现代表情符号修正了一些问题](https://oleb.net/blog/2016/12/emoji-4-0/)。


```swift
let family1 = "👨‍👩‍👧‍👦"
let family2 = "👨\u{200D}👩\u{200D}👧\u{200D}👦"
family1 == family2 // → true
```

居然还有这种操作~

### 新增 KeyPath 数据类型

KeyPath 是 Swift 4 新增加的数据类型。

定义两个结构体 `Person`与`Book` 

```swift
struct Person {
    var name: String
}

struct Book {
    var title: String
    var authors: [Person]
    var primaryAuthor: Person {
        return authors.first!
    }
}

let abelson = Person(name: "Harold Abelson")
let sussman = Person(name: "Gerald Jay Sussman")
let book = Book(title: "Structure and Interpretation of Computer Programs", authors: [abelson, sussman])
```
```swift
book[keyPath: \Book.title]
book[keyPath: \Book.primaryAuthor.name]
// 相当与
book.title
book.primaryAuthor.name
```

这里 `\Book.title` 与 `\Book.primaryAuthor.name` 就是 KeyPath.

KeyPath 可以用 `.appending` 拼接

```swift
let authorKeyPath = \Book.primaryAuthor
let nameKeyPath = authorKeyPath.appending(path: \.name)
// nameKeyPath = \Book.primaryAuthor.name
```

### 新增  `swapAt()` 函数
Swift 4 引入了一种在集合中交换两个元素的新方法: `swapAt()`

Swift 3 交换集合中的元素的用 `swap()`

```swift
var numbers = [1,2,3,4,5]
swap(&numbers[0], &numbers[1])
// numbers = [2,1,3,4,5]
```

Swift 4 中可以直接用 

```swift
var numbers = [1,2,3,4,5]
numbers.swapAt(0,1)
// numbers = [2,1,3,4,5]
```



### 其他改动

其他改动如：**新的整数协议**、**泛型下标**、**NSNumber bridging**等

可以参考：[whats new in swift4](https://github.com/ole/whats-new-in-swift-4)