傲视苍穹iOS《Swift》VIP专题

Whatʼs new in Swift 4 (Swift 4新功

2017-06-17  本文已影响126人  阿丶布布

Swift 4 新功能 -(一)

  1. 开区间
  2. 字符串
  3. 同文件内的扩展, 私有声明可见
  4. 智能Key path
  5. 编码和解码

开区间

SE-0172 带来一种新的 RangeExpression 协议和一组前缀/后缀操作符给开区间. 比如现在区间无论是上界还是下界都可以不指定.

let letters = ["a","b","c","d"]
let numberedLetters = zip(1..., letters)
Array(numberedLetters)

在集合的下标中用开区间的话, 集合的 startIndex orendIndex会“智能填充” 缺失的那一边.

let numbers = [1,2,3,4,5,6,7,8,9,10]
numbers[5...] // 取代 numbers[5..<numbers.endIndex]
打印 [6, 7, 8, 9, 10]

开区间可用于方式匹配, 比如一个 switch 语句中case 表达式 .

let value = 5
switch value {
case 1...:
    print("greater than zero")
case 0:
    print("zero")
case ..<0:
    print("less than zero")
default:
    fatalError("unreachable")
}
打印 "greater than zero"

字符串

SE-0168 带来一种简洁定义多行字符串的语法,使用 ("""). 在一个多行字符串里并不需要写转义字符, 也就是说大多数文本格式 (如JSON 或 HTML) 就可以直接粘贴而无须任何转义. 结尾三引号的缩进,决定了每一行头部被裁剪的空格多少.

let multilineString = """
    This is a multi-line string.
    You don't have to escape "quotes" in here.
    The position of the closing delimiter
      controls whitespace stripping.
    """
print(multilineString)
打印
This is a multi-line string.
You don't have to escape "quotes" in here.
The position of the closing delimiter
  controls whitespace stripping.

注意SE-0163还没完全实现并且这条建议中还有很多字符串相关的提议.

let greeting = "Hello, 😜!"
// No need to drill down to .characters
greeting.count
for char in greeting {
    print(char)
}

字符串切片现在是 Substring类型的实例. StringSubstring 两者都遵从 StringProtocol. 几乎所有字符串API都在StringProtocol 所以 StringSubstring 行为很大程度是一样的.

let comma = greeting.index(of: ",")!
let substring = greeting[..<comma]
type(of: substring)
// String API can be called on Substring
print(substring.uppercased())

Swift 4 即将支持 Unicode 9, 当前正在修正 一些时髦emoji适当的语义问题. 下面的所有字符计数是 1, 和实际的对比:

"👧🏽".count // 人 + 肤色
"👨‍👩‍👧‍👦".count // 有4个成员的家庭
"👱🏾\u{200D}👩🏽\u{200D}👧🏿\u{200D}👦🏻".count // 家庭 + 肤色
"👩🏻‍🚒".count // 人 + 肤色 + 职业

现在可以直接访问一个 Characterunicode编码值,而不用先转成String (SE-0178):

let c: Character = "🇪🇺"
Array(c.unicodeScalars)
 结果: [127466, 127482]

SE-0169 更改了访问控制规则,比如在同文件内的扩展中,原类型的private声明也是可见的. 这种改进可让同文件内保持使用private分割类型定义成为可能 , 减少不受欢迎的fileprivate关键词的使用.

struct SortedArray<Element: Comparable> {
    private var storage: [Element] = []
    init(unsorted: [Element]) {
        storage = unsorted.sorted()
    }
}

extension SortedArray {
    mutating func insert(_ element: Element) {
        // storage 此处可见
        storage.append(element)
        storage.sort()
    }
}
let array = SortedArray(unsorted: [3,1,2])
// storage 此处不可见 (不像 fileprivate)
//array.storage // error: 'storage' is inaccessible due to 'private' protection level

智能key path

SE-0161描述的新式key path有可能搞了个Swift 4的大新闻. 不像Cocoa中基于字符串的那样too simple, 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 sicp = Book(title: "Structure and Interpretation of Computer Programs", authors: [abelson, sussman])

你可以写一个key path由一个反斜杠开始: \ Book.title. 每个类型自动获取一个 [keyPath: …] 下标可以设置或获取指定key path的值.

sicp[keyPath: \Book.title]
// Key paths can to drill down and work for computed properties
sicp[keyPath: \Book.primaryAuthor.name]

let authorKeyPath = \Book.primaryAuthor
type(of: authorKeyPath)
let nameKeyPath = authorKeyPath.appending(path: \.name) // you can omit the type name if the compiler can infer it
sicp[keyPath: nameKeyPath]

Key paths 也支持下标. 如此一来可以非常便捷的深入到数组或字典这些集合类型中. 不过这功能在当前snapshot & xcode 9 beta还未实现.

//sicp[keyPath: \Book.authors[0].name]
// INTERNAL ERROR: feature not implemented: non-property key path component

压缩化 和 序列化

SE-0166: Swift Archival & Serialization 定义了一种为任意Swift类型 (class, struct, 和 enum) 来描述自身如何压缩和序列化的方法. 类型可遵从 Codable协议让自身可(解)压缩.

大多数情况下添加Codable 协议就可以让你的自定义类型完美解压缩, 因为编译器可以生成一个默认的实现,前提是所有成员类型都是Codable的. 当然你可以覆盖默认方法如果需要优化自定义类型的编码. 这个说来话长 — 还请研读SE-0166.

// Make a custom type archivable by conforming it (and all its members) to Codable
struct Card: Codable {
    enum Suit: String, Codable {
        case clubs, spades, hearts, diamonds
    }

    enum Rank: Int, Codable {
        case ace = 1, two, three, four, five, six, seven, eight, nine, ten, jack, queen, king
    }

    var suit: Suit
    var rank: Rank
}

let hand = [Card(suit: .clubs, rank: .ace), Card(suit: .hearts, rank: .queen)]

一旦有一个Codable值, 你要把它传递给一个编码器以便压缩 .

利用Codable协议的基础设施可以写自己的编解码器, 不过Swift同时为JSON提供一个内置的编解码器 (JSONEncoderJSONDecoder) 和属性列表 (PropertyListEncoderPropertyListDecoder). 这些是在 SE-0167 中定义的. NSKeyedArchiver 同样支持所有的 Codable 类型.

import Foundation

var encoder = JSONEncoder()

// JSONEncoder提供的可定制化属性
encoder.dataEncodingStrategy
encoder.dateEncodingStrategy
encoder.nonConformingFloatEncodingStrategy
encoder.outputFormatting
encoder.userInfo

let jsonData = try encoder.encode(hand)
String(data: jsonData, encoding: .utf8)

let decoder = JSONDecoder()
let decoded = try decoder.decode([Card].self, from: jsonData)
[{clubs, ace}, {hearts, queen}]

Swift 4新功能 二
英文 By Ole Begemann 中文 by 小波
相关视频

上一篇下一篇

猜你喜欢

热点阅读