Swift 4 相關功能介紹

如何安裝體驗 Swift 4

為什麼 Swift 的新功能都是 SE-xxxx

設定 target 的 Swift 版本
可針對 target 個別設定
Build Settings > Swift Language Version

Swift 版本轉換
可針對 target 個別設定

Edit > Convert > To Current Swift Syntax

Swift 4 @objc inference 的選擇,勾選 Minimize Inference 生成的 App size 較小。

SE-0168 Multi-Line String Literals,多行字串

let name = “peter”
let song = “””
原來\(name)是我最想留住的幸運
原來我們和愛情曾經靠得那麼近
那為我對抗世界的決定那陪我淋的雨
  一幕幕都是你一塵不染的真心
“””

SE-0172 One-sided Ranges,省略頭尾的 range

let movies = [“你的名字”, “我的名字”, “他的名字”]
movies[...1]
movies[..<1]
movies[1...]
movies[...]

注意: ..< 一定要指定結尾, 1..< 是錯的

SE-0104 Protocol-oriented integers,Int 和 UInt32 可以比較

SE-0169: Improve Interaction Between Private Declarations and Extensions,extension 可以讀取 private 成員

Swift 3: 
因為 private 造成 extension 裡 function intro 無法讀取 age。

解法: 改成 fileprivate。

Swift 4: 可以直接用 private。
注意: extension 必須跟型別定義在同一個檔案,才能讀取 private 的資料。

struct Woman {
  private var age = 18
  }
extension Woman {
  func intro() {
    print(“我的年紀是\(age)”)
  }
}

SE-0156: Class and Subtype Existentials,可以用 & 結合 class 和 protocol

protocol Shakeable {
func shake()
}
extension UIButton: Shakeable {
func shake() {
print(“shake”)
}
}
func shakeThem(controls: [UIControl]) {
for control in controls where control.isEnabled {
control.shake()
}
}
shakeThem(controls: [UIButton(), UIButton()])
func shakeThem(controls: [Shakeable]) {
for control in controls where control.isEnabled {
control.shake()
}
}

在 Swift 3, & 只能結合 protocol。在 Swift 4,& 也可以結合 class 和 protocol。

func shakeThem(controls: [UIControl & Shakeable]) {
for control in controls where control.isEnabled {
control.shake()
}
}
var but:UIControl & Shakeable = UIButton()

SE-0163 String as a Collection,把字串當成集合來使用

Swift 3 要透過 characters。

var song = “原來你是我最想留住的幸運”
for char in song.characters {
print(char)
}
song.characters.count
song.characters.dropFirst()
song.characters.dropFirst(2)
song.characters.dropLast()
song.characters.dropLast(2)
song.characters.reversed()
song.characters.filter { (char) -> Bool in
if char == “彼” || char == “得” || char == “潘” {
return true
}
else {
return false
}
}

Swift 4 可以直接把字串當成集合來使用。

var song = “原來彼得潘是我最想留住的幸運”
for char in song {
print(char)
}
song.count
song.dropFirst()
song.dropFirst(2)
song.dropLast()
song.dropLast(2)
song.reversed()
song.filter { (char) -> Bool in
if char == “彼” || char == “得” || char == “潘” {
return true
}
else {
return false
}
}

SE-0165 Dictionary & Set Enhancements

dictionary 找不到對應 value 時有預設值。

let dic = [“楊過”:”小龍女”, “彼得潘”:”溫蒂”]
dic[“虎克”, default:”虎姑婆”]

將 array 裡的成員分類,生成 dictionary。

struct Idol {
var name: String
var gender: String
}
var myIdols = [Idol(name: “劉德華”, gender: “男”), Idol(name: “張智霖”, gender: “男”), Idol(name: “戴佩妮”, gender: “女”)]
let idolDic = Dictionary(grouping: myIdols) { (idol) -> String in
return idol.gender
}
idolDic[“男”]

從 sequence 產生 dictionary

let names = ["楊過", "郭靖", "令狐沖"]
let skills = ["黯然銷魂掌", "降龍十八掌", "獨孤九劍"]
let nameAndSkills = zip(names, skills)
for data in nameAndSkills {
print(data)
}
let dic = Dictionary(uniqueKeysWithValues: nameAndSkills)
dic

SE-0173 Array Swap

var boyFriends = [“劉德華”, “梁朝偉”, “金城武”, “彼得潘”]
boyFriends.swapAt(0, 3)

SE-0166 Swift Archival & Serialization

可作用於 class, struct, enum

例子: song.json

{
“name”:”街角的祝福”,
“album”:”Just Sing It”,
“artist”:”戴佩妮”
}

從 JSON data 生成自訂的型別

struct Song:Codable {
var name:String
var album:String
var artist:String
}
let url = Bundle.main.url(forResource: “song”, withExtension: “json”)
let data = try? Data(contentsOf: url!)
if let data = data {
let jsonDecoder = JSONDecoder()
let song = try? jsonDecoder.decode(Song.self, from: data)
if let song = song {
print(song.name)
}
}

從自訂的型別生成 JSON data

struct Song:Codable {
var name:String
var album:String
var artist:String
}
let jsonEncoder = JSONEncoder()
let song = Song(name: “怎樣”, album: “怎樣”, artist: “戴佩妮”)
let jsonData = try? jsonEncoder.encode(song)
if let jsonData = jsonData {
let jsonString = String(data: jsonData, encoding: .utf8)
}

SE-0161 Key-Value Coding

利用 key path 方便存取 property

struct Woman {
var name:String
}
struct Man {
var name:String
var girlFriend:Woman
}
let woman1 = Woman(name: “wendy”)
let woman2 = Woman(name: “虎姑婆”)
let man1 = Man(name:”peter”, girlFriend:woman1)
let man2 = Man(name:”hook”, girlFriend:woman2)
let nameKeyPath = \Man.girlFriend.name
let name1 = man1[keyPath:nameKeyPath]
let name2 = man2[keyPath:nameKeyPath]