[简译] What’s New in Swift 3.1?

一、Swift 3.1 篇

  1. Xcode 8.3 不向下支持 swift 2.3
  2. 所有数值类型(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,则成功。

  1. 新的序列函数: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}
  1. 用具体的类型约束扩展泛型,以前的类型约束必须是协议
// 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
  }
}
  1. 嵌套泛型
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   
  }
}
  1. 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)
}
  1. 将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 篇

  1. 开发者可以利用新的API在App内通过弹窗的方式请求用户直接给出评分,不再需要前往App Store。防止滥用,每一个APP 每年只能使用3次。但是依然可以继续使用原来的弹窗方式。
  2. 开发者可以随时更新App的图标(更换图标前需要得到用户的许可),不再需要通过更新App实现。

你可能感兴趣的:([简译] What’s New in Swift 3.1?)