Swift新變化(一) —— Swift 5.1新變化(一)

版本記錄

版本號 時(shí)間
V1.0 2019.08.01 星期四

前言

幾乎隨著每一版iOS新系統(tǒng)的發(fā)布,Swift都會有所改變,加入了更多的特性,下面我們就一起走進(jìn)看一下相關(guān)的變化。

開始

首先,看下主要內(nèi)容

主要內(nèi)容:Swift 5.1的新變化。

接著,看下寫作環(huán)境

Swift 5, iOS 13, Xcode 11

好消息:Swift 5.1現(xiàn)在可以在Xcode 11 beta中使用!此版本帶來了模塊穩(wěn)定性(module stability),并通過改進(jìn)了語言的重要特征。在本教程中,您將了解Swift 5.1中的新功能。您需要Xcode 11 beta才能使用Swift 5.1,因此請?jiān)陂_始之前安裝它。

Swift 5.1Swift 5兼容。由于ABI stability,它還與Swift 5以及未來版本的Swift二進(jìn)制兼容。

Swift 5.1在Swift 5中引入的ABI stability之上增加了模塊穩(wěn)定性。雖然ABI穩(wěn)定性在運(yùn)行時(shí)負(fù)責(zé)應(yīng)用程序兼容性,但模塊穩(wěn)定性使編譯時(shí)的庫兼容性成為可能。這意味著您可以將第三方框架與任何編譯器版本一起使用,而不是僅使用它構(gòu)建的版本。

每個教程部分都包含Swift Evolution建議編號,例如[SE-0001]。您可以通過單擊每個提案的鏈接標(biāo)記來瀏覽每個更改。

我建議您通過在playground上嘗試新功能來學(xué)習(xí)本教程。啟動Xcode 11并轉(zhuǎn)到File ? New ? Playground。選擇iOS作為平臺,選擇Blank作為模板。將其命名并將其保存在您想要的位置。那么就是時(shí)候開始了!


Language Improvements

此版本中有許多語言改進(jìn),包括不透明的結(jié)果類型,函數(shù)構(gòu)建器,屬性包裝器等。

1. Opaque Result Types

您可以使用協(xié)議作為Swift 5中函數(shù)的返回類型。

打開新的Playground后,通過導(dǎo)航到View ? Navigators ? Show Project Navigator打開Project Navigator。 右鍵單擊Sources文件夾,選擇New File并將文件命名為BlogPost。 使用名為BlogPost的新協(xié)議的定義替換新文件的內(nèi)容。

public protocol BlogPost {
  var title: String { get }
  var author: String { get }
}

右鍵單擊頂層playground并選擇New Playground Page。 重命名新的playground頁面Opaque Tutorials并將其粘貼到其中:

// 1
struct Tutorial: BlogPost {
  let title: String
  let author: String
}

// 2
func createBlogPost(title: String, author: String) -> BlogPost {
  guard !title.isEmpty && !author.isEmpty else {
    fatalError("No title and/or author assigned!")
  }
  return Tutorial(title: title, author: author)
}

// 3
let swift4Tutorial = createBlogPost(title: "What's new in Swift 4.2?",
                                    author: "Cosmin Pup?z?")
let swift5Tutorial = createBlogPost(title: "What's new in Swift 5?", 
                                    author: "Cosmin Pup?z?")

這一步一步:

  • 1) 聲明Tutorialtitleauthor,因?yàn)?code>Tutorial實(shí)現(xiàn)了BlogPost。
  • 2) 檢查titleauthor是否有效,如果測試成功,則從createBlogPost(title:author :)返回Tutorial
  • 3) 使用createBlogPost(title:author :)創(chuàng)建swift4Tutorialswift5Tutorial。

您可以重復(fù)使用createBlogPost(title:author :)的原型和邏輯來創(chuàng)建截屏視頻。

右鍵單擊頂層playground并選擇New Playground Page。 重命名新的playground頁面Opaque Screencasts并將其粘貼到其中:

struct Screencast: BlogPost {
  let title: String
  let author: String
}

func createBlogPost(title: String, author: String) -> BlogPost {
  guard !title.isEmpty && !author.isEmpty else {
    fatalError("No title and/or author assigned!")
  }
  return Screencast(title: title, author: author)
}

let swift4Screencast = createBlogPost(title: "What's new in Swift 4.2?", 
                                      author: "Josh Steele")           
let swift5Screencast = createBlogPost(title: "What's new in Swift 5?", 
                                      author: "Josh Steele")

Screencast實(shí)現(xiàn)了BlogPost,因此您可以從createBlogPost(title:author :)返回Screencast,并使用createBlogPost(title:author :)來創(chuàng)建swift4Screencastswift5Screencast

導(dǎo)航到Sources文件夾中的BlogPost.swift,并使BlogPost符合Equatable。

public protocol BlogPost: Equatable {
  var title: String { get }
  var author: String { get }
}

此時(shí),您將收到一個錯誤,即BlogPost只能用作generic constraint。 這是因?yàn)?code>Equatable有一個名為Self的關(guān)聯(lián)類型。 具有關(guān)聯(lián)類型的協(xié)議不是類型,即使它們看起來像類型。 相反,它們有點(diǎn)像類型占位符,表示“這可以是符合此協(xié)議的任何具體類型”。

Swift 5.1允許您將這些協(xié)議用作具有不透明結(jié)果類型的常規(guī)類型 opaque result types [SE-0244]。

Opaque Tutorials頁面中,將some添加到createBlogPost的返回類型中,表示它返回BlogPost的具體實(shí)現(xiàn)。

func createBlogPost(title: String, author: String) -> some BlogPost {

同樣,在Opaque Screencasts頁面中,使用some來告訴編譯器createBlogPost返回某種類型的BlogPost。

func createBlogPost(title: String, author: String) -> some BlogPost {

在這種情況下,您可以從createBlogPost返回任何實(shí)現(xiàn)BlogPost的具體類型:TutorialScreencast。

現(xiàn)在,您可以檢查以前創(chuàng)建的教程和截屏是否相同。 在Opaque Tutorials的底部,粘貼以下內(nèi)容以檢查swift4Tutorialswift5Tutorial是否相同。

let sameTutorial = swift4Tutorial == swift5Tutorial

Opaque Screencasts的底部,粘貼以下內(nèi)容以檢查swift4Screencastswift5Screencast是否相同。

let sameScreencast = swift4Screencast == swift5Screencast

2. Implicit Returns From Single-Expression Functions

Swift 5中使用單表達(dá)式函數(shù)中的return

extension Sequence where Element == Int {
  func addEvenNumbers() -> Int {
    return reduce(0) { $1.isMultiple(of: 2) ? $0 + $1 : $0 }
  }

  func addOddNumbers() -> Int {
    return reduce(0) { $1.isMultiple(of: 2) ? $0 : $0 + $1 }
  }
}

let numbers = [10, 5, 2, 7, 4]
let evenSum = numbers.addEvenNumbers()
let oddSum = numbers.addOddNumbers()

您在addEvenNumbers()addOddNumbers()中使用reduce(_:_ :)來確定Sequence中偶數(shù)和奇數(shù)的總和。

Swift 5.1在單表達(dá)式函數(shù)中return,因此在這種情況下它們的行為類似于單行閉包[SE-0255]:

extension Sequence where Element == Int {
  func addEvenNumbers() -> Int {
    reduce(0) { $1.isMultiple(of: 2) ? $0 + $1 : $0 }
  }

  func addOddNumbers() -> Int {
    reduce(0) { $1.isMultiple(of: 2) ? $0 : $0 + $1 }
  }
}

這次代碼更清晰,更容易理解。

3. Function Builders

Swift 5.1使用函數(shù)構(gòu)建器(function builders)來實(shí)現(xiàn)構(gòu)建器模式 builder pattern[SE-XXXX]:

@_functionBuilder
struct SumBuilder {
  static func buildBlock(_ numbers: Int...) -> Int {
    return numbers.reduce(0, +)
  }
}

使用@_functionBuilder注釋SumBuilder,使其成為函數(shù)構(gòu)建器類型。 函數(shù)構(gòu)建器是特殊類型的函數(shù),其中每個表達(dá)式(文字,變量名,函數(shù)調(diào)用,if語句等)單獨(dú)處理并用于生成單個值。 例如,您可以編寫一個函數(shù),其中每個表達(dá)式將該表達(dá)式的結(jié)果添加到數(shù)組中,從而創(chuàng)建您自己的數(shù)組文字。

注意:在Xcode測試版中,函數(shù)構(gòu)建器的注釋是@_functionBuilder,因?yàn)榇颂嶙h尚未獲得批準(zhǔn)。 一旦獲得批準(zhǔn),期望注釋成為@functionBuilder

您可以通過實(shí)現(xiàn)具有特定名稱和類型簽名的不同靜態(tài)函數(shù)來創(chuàng)建函數(shù)構(gòu)建器。 buildBlock(_:T ...)是唯一需要的。 還有一些函數(shù)可以處理if語句,選項(xiàng)和其他可以作為表達(dá)式處理的結(jié)構(gòu)。

您可以通過使用類名注釋函數(shù)或閉包來使用函數(shù)構(gòu)建器:

func getSum(@SumBuilder builder: () -> Int) -> Int {
  builder()
}

let gcd = getSum {
  8
  12
  5
}

傳遞給getSum的閉包計(jì)算每個表達(dá)式(在本例中為三個數(shù)字),并將這些表達(dá)式的結(jié)果列表傳遞給構(gòu)建器。 函數(shù)構(gòu)建器和隱式返回是SwiftUI干凈語法的構(gòu)建塊。 它們還允許您創(chuàng)建自己的特定于域的語言。

4. Property Wrappers

Swift 5中使用計(jì)算屬性時(shí),你會處理很多樣板代碼:

var settings = ["swift": true, "latestVersion": true]

struct Settings {
  var isSwift: Bool {
    get {
      return settings["swift"] ?? false
    }
    set {
      settings["swift"] = newValue
   }
  }

  var isLatestVersion: Bool {
    get {
      return settings["latestVersion"] ?? false
    }
    set {
      settings["latestVersion"] = newValue
    }
  }
}

var newSettings = Settings()
newSettings.isSwift
newSettings.isLatestVersion
newSettings.isSwift = false
newSettings.isLatestVersion = false

isSwiftisLatestVersionsettings中獲取并設(shè)置給定鍵的值。 Swift 5.1通過定義property wrappers[SE-0258]來刪除重復(fù)代碼:

// 1
@propertyWrapper
struct SettingsWrapper {
  let key: String
  let defaultValue: Bool

  // 2
  var wrappedValue: Bool {
    get {
      settings[key] ?? defaultValue
    }
    set {
      settings[key] = newValue
    }
  }
}

// 3
struct Settings {
  @SettingsWrapper(key: "swift", defaultValue: false) var isSwift: Bool
  @SettingsWrapper(key: "latestVersion", defaultValue: false) 
    var isLatestVersion: Bool
}

這就是上面代碼的工作原理:

  • 1) 使用@propertyWrapper注釋SettingsWrapper,使其成為屬性包裝器類型。
  • 2) 使用wrappedValue獲取并設(shè)置settings中的key。
  • 3) 標(biāo)記isSwiftisLatestVersion@SettingsWrapper用相應(yīng)的包裝器實(shí)現(xiàn)它們。
Working with computed properties the Swifty way!

5. Synthesizing Default Values for Initializers in Structures

默認(rèn)情況下,Swift 5不會為結(jié)構(gòu)中的屬性設(shè)置初始值,因此您可以為它們定義自定義初始值設(shè)定項(xiàng):

struct Author {
  let name: String
  var tutorialCount: Int

  init(name: String, tutorialCount: Int = 0) {
    self.name = name
    self.tutorialCount = tutorialCount
  }
}

let author = Author(name: "George")

如果author已經(jīng)通過了他的試用并加入了網(wǎng)站上的教程團(tuán)隊(duì),那么你將這里設(shè)置tutorialCount0

Swift 5.1允許您直接為結(jié)構(gòu)屬性設(shè)置默認(rèn)值,因此不再需要自定義初始值設(shè)定項(xiàng)[SE-0242]:

struct Author {
  let name: String
  var tutorialCount = 0
}

這次代碼更簡潔,更簡單。

6. Self for Static Members

您不能使用SelfSwift 5中引用數(shù)據(jù)類型的靜態(tài)成員,因此您必須使用類型名稱:

struct Editor {
  static func reviewGuidelines() {
    print("Review editing guidelines.")
  }

  func edit() {
    Editor.reviewGuidelines()
    print("Ready for editing!")
  }
}

let editor = Editor()
editor.edit()

網(wǎng)站上的編輯在編輯教程之前會查看編輯指南,因?yàn)樗鼈兛偸菚l(fā)生變化。

你可以在Swift 5.1中使用Self重寫整個東西[SE-0068]:

struct Editor {
  static func reviewGuidelines() {
    print("Review editing guidelines.")
  }

  func edit() {
    Self.reviewGuidelines()
    print("Ready for editing!")
  }
}

你這次使用Self來調(diào)用reviewGuidelines()。

7. Creating Uninitialized Arrays

您可以在Swift 5.1中創(chuàng)建未初始化的數(shù)組[SE-0245]:

// 1
let randomSwitches = Array<String>(unsafeUninitializedCapacity: 5) {
  buffer, count in
  // 2
  for i in 0..<5 {
    buffer[i] = Bool.random() ? "on" : "off"
  }
  // 3
  count = 5
}

逐步完成上面的代碼:

  • 1) 使用init(unsafeUninitializedCapacity:initializingWith :)創(chuàng)建具有特定初始容量的randomSwitches。
  • 2) 循環(huán)遍歷randomSwitches并使用random()設(shè)置每個開關(guān)狀態(tài)。
  • 3) 設(shè)置randomSwitches的初始化元素?cái)?shù)。

8. Diffing Ordered Collections

Swift 5.1使您能夠確定有序集合之間的差異[SE-0240]。

假設(shè)您有兩個數(shù)組:

let operatingSystems = ["Yosemite",
                        "El Capitan",
                        "Sierra",
                        "High Sierra",
                        "Mojave",
                        "Catalina"]
var answers = ["Mojave",
               "High Sierra",
               "Sierra",
               "El Capitan",
               "Yosemite",
               "Mavericks"]

operatingSystems包含自Swift 1從最舊到最新排列的所有macOS版本。 answers在添加和刪除其中一些時(shí)以相反的順序列出它們。

差異集合需要您使用#if swift(> =)檢查最新的Swift版本,因?yàn)樗?code>diffing方法僅標(biāo)記為@available,僅適用于Swift 5.1

#if swift(>=5.1)
  let differences = operatingSystems.difference(from: answers)
  let sameAnswers = answers.applying(differences) ?? []
  // ["Yosemite", "El Capitan", "Sierra", "High Sierra", "Mojave", "Catalina"]

通過difference(from:)獲取operatingSystemsanswers之間的differences,并使用applying(_:)將它們應(yīng)用于answers。

或者,您可以手動執(zhí)行此操作:

  // 1
  for change in differences.inferringMoves() {
    switch change {
      // 2
      case .insert(let offset, let element, let associatedWith):
        answers.insert(element, at: offset)
        guard let associatedWith = associatedWith else {
          print("\(element) inserted at position \(offset + 1).")
          break
        }
        print("""
              \(element) moved from position \(associatedWith + 1) to position 
              \(offset + 1).
              """)
      // 3
      case .remove(let offset, let element, let associatedWith):
        answers.remove(at: offset)
        guard let associatedWith = associatedWith else {
          print("\(element) removed from position \(offset + 1).")
          break
        }
        print("""
              \(element) removed from position \(offset + 1) because it should be 
                at position \(associatedWith + 1).
              """)
    }
  }
#endif

這是代碼的作用:

  • 1) 使用inferringMoves()來確定differences中的移動并遍歷它們。
  • 2) 如果change.insert(offset:element:associatedWith :),則將offset處的element添加到answers中,如果associatedWith不為nil,則將插入視為removal。
  • 3) 如果change.remove(offset:element:associatedWith :),則刪除answersoffset答案的element,如果associatedWith不為nil,則考慮刪除removal
Diffing collections like a pro in Swift 5.1!

9. Static and Class Subscripts

Swift 5.1允許您在[SE-0254]中聲明staticclass subscripts

// 1
@dynamicMemberLookup
class File {
  let name: String

  init(name: String) {
    self.name = name
  }

  // 2
  static subscript(key: String) -> String {
    switch key {
      case "path":
        return "custom path"
      default:
        return "default path"
    }
  }

  // 3
  class subscript(dynamicMember key: String) -> String {
    switch key {
      case "path":
        return "custom path"
      default:
        return "default path"
    }
  }
}

// 4
File["path"]
File["PATH"]
File.path
File.PATH

這就是它的工作原理:

  • 1) 將File標(biāo)記為@dynamicMemberLookup以啟用custom subscripts的點(diǎn)語法。
  • 2) 創(chuàng)建一個靜態(tài)subscript,返回File的默認(rèn)路徑或自定義路徑。
  • 3) 使用動態(tài)成員查找定義上一個subscript的類版本。
  • 4) 使用相應(yīng)的語法調(diào)用兩個subscript

注意:想要了解有關(guān)Swift中下標(biāo)的更多信息? 查看下標(biāo)教程:Swift中的自定義下標(biāo)。

10. Dynamic Member Lookup for Keypaths

Swift 5.1實(shí)現(xiàn)了關(guān)鍵路徑的動態(tài)成員查找[SE-0252]:

// 1
struct Point {
  let x, y: Int
}

// 2
@dynamicMemberLookup
struct Circle<T> {
  let center: T
  let radius: Int

  // 3
  subscript<U>(dynamicMember keyPath: KeyPath<T, U>) -> U {
    center[keyPath: keyPath]
  }
}

// 4
let center = Point(x: 1, y: 2)
let circle = Circle(center: center, radius: 1)
circle.x
circle.y

逐步完成所有這些步驟:

  • 1) 為Point聲明xy。
  • 2) 使用@dynamicMemberLookup注釋Circle以為其subscripts啟用點(diǎn)語法。
  • 3) 創(chuàng)建一個通用subscripts,使用鍵路徑從Circle訪問center屬性。
  • 4) 使用動態(tài)成員查找而不是鍵路徑調(diào)用circle上的調(diào)用center屬性。

11. Keypaths for Tuples

您可以在Swift 5.1中使用元組的路徑:

// 1
struct Instrument {
  let brand: String
  let year: Int
  let details: (type: String, pitch: String)
}

// 2
let instrument = Instrument(brand: "Roland",
                            year: 2019,
                            details: (type: "acoustic", pitch: "C"))
let type = instrument[keyPath: \Instrument.details.type]
let pitch = instrument[keyPath: \Instrument.details.pitch]

下面就是要做的事:

  • 1) 聲明Instrumentrand, year, details。
  • 2) 使用關(guān)鍵路徑從instrument中的details中獲取type, pitch。

12. Equatable and Hashable Conformance for Weak and Unowned Properties

Swift 5.1自動為具有weakunowned存儲屬性的結(jié)構(gòu)合成EquatableHashableconformance

假設(shè)你有兩個類:

class Key {
  let note: String

  init(note: String) {
    self.note = note
  }
}

extension Key: Hashable {
  static func == (lhs: Key, rhs: Key) -> Bool {
    lhs.note == rhs.note
  }

  func hash(into hasher: inout Hasher) {
    hasher.combine(note)
  }
}

class Chord {
  let note: String

  init(note: String) {
    self.note = note
  }
}

extension Chord: Hashable {
  static func == (lhs: Chord, rhs: Chord) -> Bool {
    lhs.note == rhs.note
  }

  func hash(into hasher: inout Hasher) {
    hasher.combine(note)
  }
}

通過實(shí)現(xiàn)==(lhs:rhs :)hash(into :),KeyChord都符合EquatableHashable。

如果在結(jié)構(gòu)中使用這些類,Swift 5.1將能夠合成Hashable conformance

struct Tune: Hashable {
  unowned let key: Key
  weak var chord: Chord?
}

let key = Key(note: "C")
let chord = Chord(note: "C")
let tune = Tune(key: key, chord: chord)
let chordlessTune = Tune(key: key, chord: nil)
let sameTune = tune == chordlessTune
let tuneSet: Set = [tune, chordlessTune]
let tuneDictionary = [tune: [tune.key.note, tune.chord?.note], 
                      chordlessTune: [chordlessTune.key.note, 
                      chordlessTune.chord?.note]]

TuneEquatableHashable,因?yàn)?code>key和chordEquatableHashable。

因?yàn)樗?code>Hashable,你可以將tunechordlessTune進(jìn)行比較,將它們添加到tuneSet并將它們用作tuneDictionary的鍵。

13. Ambiguous Enumeration Cases

Swift 5.1為不明確的枚舉cases生成警告:

// 1
enum TutorialStyle {
  case cookbook, stepByStep, none
}

// 2
let style: TutorialStyle? = .none

下面就是工作原理:

  • 1) 為TutorialStyle定義不同的樣式。
  • 2) Swift會發(fā)出警告,因?yàn)榫幾g器不清楚.nonecase: Optional.noneTutorialStyle.none的含義是什么。

14. Matching Optional Enumerations Against Non-optionals

在Swift 5中,您可以使用optional patternnon-optionals與的可選枚舉optional enumerations進(jìn)行匹配:

// 1
enum TutorialStatus {
  case written, edited, published
}

// 2
let status: TutorialStatus? = .published

switch status {
  case .written?:
    print("Ready for editing!")
  case .edited?:
    print("Ready to publish!")
  case .published?:
    print("Live!")
  case .none:
    break
}

上面的代碼執(zhí)行以下操作:

  • 1) 聲明TutorialStatus的所有可能狀態(tài)。
  • 2) 使用可選模式打開status,因?yàn)槟鷮⑵涠x為可選模式。

在這種情況下,Swift 5.1刪除了可選的模式(optional pattern)

switch status {
  case .written:
    print("Ready for editing!")
  case .edited:
    print("Ready to publish!")
  case .published:
    print("Live!")
  case .none:
    break
}

這段代碼更清晰,更容易理解。

15. New Features for Strings

Swift 5.1為字符串添加了一些急需的功能[SE-0248]:

UTF8.width("S")
UTF8.isASCII(83)

在這里,您確定Unicode標(biāo)量值的UTF-8編碼寬度,并檢查給定的代碼單元是否表示ASCII標(biāo)量。 查看您可以使用的其他API的proposal。

16. Contiguous Strings

Swift 5.1對連續(xù)字符串(contiguous strings)[SE-0247]實(shí)現(xiàn)重要更改:

var string = "Swift 5.1"
if !string.isContiguousUTF8 {
  string.makeContiguousUTF8()
}

您檢查UTF-8編碼的字符串是否與isContiguousUTF8連續(xù),并使用makeContiguousUTF8()來實(shí)現(xiàn),如果不是。 看一下提案(proposal),看看你可以用連續(xù)的字符串做些什么。


Miscellaneous Bits and Pieces

您應(yīng)該了解Swift 5.1中的一些其他功能:

1. Converting Tuple Types

Swift 5.1改進(jìn)了元組類型的轉(zhuǎn)換:

let temperatures: (Int, Int) = (25, 30)
let convertedTemperatures: (Int?, Any) = temperatures

您可以為convertedTemperatures賦值為temperatures,因?yàn)樵谶@種情況下您可以將(Int,Int)轉(zhuǎn)換為(Int?,Any)。

2. Tuples with Duplicate Labels

您可以在Swift 5中聲明帶有重復(fù)標(biāo)簽的元組:

let point = (coordinate: 1, coordinate: 2)
point.coordinate

在這種情況下,不清楚coordinate是否從point返回第一個或第二個元素,因此Swift 5.1刪除了元組的重復(fù)標(biāo)簽。

3. Overloading Functions With Any Parameters

Swift 5更喜歡Any參數(shù)而不是泛型參數(shù),只有一個參數(shù)的函數(shù)重載:

func showInfo(_: Any) -> String {
  return "Any value"
}

func showInfo<T>(_: T) -> String {
  return "Generic value"
}

showInfo("Swift 5")

在這種case下,showInfo()返回“Any value”。Swift 5.1以相反的方式工作:

func showInfo(_: Any) -> String {
  "Any value"
}

func showInfo<T>(_: T) -> String {
  "Generic value"
}

showInfo("Swift 5.1")

showInfo()這次返回“Generic value”

4. Type Aliases for Autoclosure Parameters

你不能在Swift 5中為@autoclosure參數(shù)聲明類型別名(type aliases)

struct Closure<T> {
  func apply(closure: @autoclosure () -> T) {
    closure()
  }
}

apply(closure :)在這種情況下使用autoclosure簽名進(jìn)行closure。 您可以在Swift 5.1中的apply(closure :)原型中使用類型別名:

struct Closure<T> {
  typealias ClosureType = () -> T

  func apply(closure:  @autoclosure ClosureType) {
    closure()
  }
}

apply(closure :)這次使用ClosureType進(jìn)行閉包closure

5. Returning Self From Objective-C methods

如果你的類包含一個在Swift 5中返回Self@objc方法,你必須從NSObject繼承:

class Clone: NSObject {
  @objc func clone() -> Self {
    return self
  }
}

Clone擴(kuò)展了NSObject,因?yàn)?code>clone()返回Self。 在Swift 5.1中不再是這種情況:

class Clone {
  @objc func clone() -> Self {
    self
  }
}

Clone這次不必繼承任何東西。

6. Stable ABI Libraries

您可以在Swift 5.1中使用-enable-library-evolution來更改庫類型而不會破壞其ABI。 標(biāo)記為@frozen的結(jié)構(gòu)和枚舉不能添加,刪除或重新排序存儲的屬性和cases [SE-0260]。

Swift 5.1Swift 5中已經(jīng)引入的功能添加了許多不錯的功能。它還為語言帶來了模塊穩(wěn)定性(module stability),并實(shí)現(xiàn)了WWDC中引入的新框架(如SwiftUICombine)所使用的復(fù)雜范例。

您可以在官方 Swift CHANGELOGSwift standard library differences上閱讀有關(guān)此Swift版本更改的更多信息。

后記

本篇主要講述了Swift 5.1新變化,感興趣的給個贊或者關(guān)注~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容