一、Swift 3.1 篇
- Xcode 8.3 不向下支持 swift 2.3
- 所有数值类型(Int, Int8, Int16, Int32, Int64, UInt, UInt8, UInt16, UInt32, UInt64, Float, Float80, Double)都实现了可失败初始化器(failable initializers)
class Student {
let name: String
let grade: Int
init?(json: [String: Any]) {
guard let name = json["name"] as? String,
let gradeString = json["grade"] as? String,
let gradeDouble = Double(gradeString),
let grade = Int(exactly: gradeDouble) // <-- 3.1 feature here
else {
return nil
}
self.name = name
self.grade = grade
}
}
func makeStudents(with data: Data) -> [Student] {
guard let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments),
let jsonArray = json as? [[String: Any]] else {
return []
}
return jsonArray.flatMap(Student.init)
}
let rawStudents = "[{\"name\":\"Ray\", \"grade\":\"5.0\"}, {\"name\":\"Matt\", \"grade\":\"6\"},
{\"name\":\"Chris\", \"grade\":\"6.33\"}, {\"name\":\"Cosmin\", \"grade\":\"7\"},
{\"name\":\"Steven\", \"grade\":\"7.5\"}]"
let data = rawStudents.data(using: .utf8)!
let students = makeStudents(with: data)
dump(students) // [(name: "Ray", grade: 5), (name: "Matt", grade: 6), (name: "Cosmin", grade: 7)]
let grade = Int(exactly: gradeDouble)
如果gradeDouble 是碎片值,比如 6.33,则失败,如果是Int值,比如6.0,则成功。
- 新的序列函数:
prefix(while:)
和drop(while:)
let fibonacci = sequence(state: (0, 1)) {
(state: inout (Int, Int)) -> Int? in
defer {state = (state.1, state.0 + state.1)}
return state.0
}
// Swift 3.0
for number in fibonacci.prefix(10) {
print(number) // 0 1 1 2 3 5 8 13 21 34
}
// Swift 3.1
let interval = fibonacci.prefix(while: {$0 < 1000}).drop(while: {$0 < 100})
for element in interval {
print(element) // 144 233 377 610 987
}
// trailing closure syntax
let interval = fibonacci.prefix{$0 < 1000}.drop{$0 < 100}
- 用具体的类型约束扩展泛型,以前的类型约束必须是协议
// Swift 3.0
extension String {
var isBlank: Bool {
return trimmingCharacters(in: .whitespaces).isEmpty
}
}
let abc = " "
let def = "x"
abc.isBlank // true
def.isBlank // false
// Swift 3.0
protocol StringProvider {
var string: String {get}
}
extension String: StringProvider {
var string: String {
return self
}
}
extension Optional where Wrapped: StringProvider {
var isBlank: Bool {
return self?.string.isBlank ?? true
}
}
let foo: String? = nil
let bar: String? = " "
let baz: String? = "x"
foo.isBlank // true
bar.isBlank // true
baz.isBlank // false
// Swift 3.1
extension Optional where Wrapped == String {
var isBlank: Bool {
return self?.isBlank ?? true
}
}
- 嵌套泛型
class Team {
enum TeamType {
case swift
case iOS
case macOS
}
class BlogPost {
enum BlogPostType {
case tutorial
case article
}
let title: T
let type: BlogPostType
let category: TeamType
let publishDate: Date
init(title: T, type: BlogPostType, category: TeamType, publishDate: Date) {
self.title = title
self.type = type
self.category = category
self.publishDate = publishDate
}
}
let type: TeamType
let author: T
let teamLead: T
let blogPost: BlogPost
init(type: TeamType, author: T, teamLead: T, blogPost: BlogPost) {
self.type = type
self.author = author
self.teamLead = teamLead
self.blogPost = blogPost
}
}
默认继承泛型,简化:
Team(type: .swift, author: "Cosmin Pupăză", teamLead: "Ray Fix",
blogPost: Team.BlogPost(title: "Pattern Matching", type: .tutorial,
category: .swift, publishDate: Date()))
Team(type: .swift, author: "Cosmin Pupăză", teamLead: "Ray Fix",
blogPost: Team.BlogPost(title: "What's New in Swift 3.1?", type: .article,
category: .swift, publishDate: Date()))
class Team {
// original code
class BlogPost {
// original code
}
// original code
let blogPost: BlogPost
init(type: TeamType, author: T, teamLead: T, blogPost: BlogPost) {
// original code
}
}
- Swift 版本可用性
// Swift 3.0
#if swift(>=3.1)
func intVersion(number: Double) -> Int? {
return Int(exactly: number)
}
#elseif swift(>=3.0)
func intVersion(number: Double) -> Int {
return Int(number)
}
#endif
// Swift 3.1
@available(swift 3.1)
func intVersion(number: Double) -> Int? {
return Int(exactly: number)
}
@available(swift, introduced: 3.0, obsoleted: 3.1)
func intVersion(number: Double) -> Int {
return Int(number)
}
- 将Non-Escaping Closures 转换为 Escaping Ones
使用函数:withoutActuallyEscaping()
func perform(_ f: () -> Void, simultaneouslyWith g: () -> Void,
on queue: DispatchQueue) {
withoutActuallyEscaping(f) { escapableF in // 1
withoutActuallyEscaping(g) { escapableG in
queue.async(execute: escapableF) // 2
queue.async(execute: escapableG)
queue.sync(flags: .barrier) {} // 3
} // 4
}
}
二、iOS 10.3 篇
- 开发者可以利用新的API在App内通过弹窗的方式请求用户直接给出评分,不再需要前往App Store。防止滥用,每一个APP 每年只能使用3次。但是依然可以继续使用原来的弹窗方式。
- 开发者可以随时更新App的图标(更换图标前需要得到用户的许可),不再需要通过更新App实现。