Swift 5.9 新特性

Swift 5.9 內(nèi)置于 Xcode 15,雖然是 Swift 5 的最后一個(gè)大版本,仍然增加了不少新特性。

if與switch表達(dá)式

ifswitch語句可以作為表達(dá)式使用。

let score = 90
let result1 = if score >= 60 {
    "及格"
} else {
    "不及格"
}
print(result1)

let result2 = switch score {
case 0 ..< 60:
    "不及格"
case 60 ..< 70:
    "及格"
case 70 ..< 80:
    "中等"
case 89 ..< 90:
    "良好"
case 90 ... 100:
    "優(yōu)秀"
default:
    "其他"
}
print(result2)

~Copyable不可復(fù)制

  • 引入了“不可復(fù)制的枚舉與結(jié)構(gòu)體”的概念。
  • 不可復(fù)制的枚舉與結(jié)構(gòu)體需要遵守~Copyable協(xié)議。
  • 枚舉與結(jié)構(gòu)體如果遵守了~Copyable協(xié)議,則除了Sendable協(xié)議再也不能遵守其他任何協(xié)議。
struct Person: ~Copyable {
    var name = "Zhangsan"
    var age = 10
    let sex = "male"
}

let person = Person()
print(person.name, person.age, person.sex)

// 報(bào)錯(cuò):Cannot consume noncopyable stored property 'person' that is global
let personCopy = person
print(personCopy.name, personCopy.age, personCopy.sex)

Clock增加sleep(for:)方法

let clock1 = ContinuousClock()
try? await clock1.sleep(for: .seconds(1))
let clock2 = SuspendingClock()
try? await clock2.sleep(for: .seconds(1))

// 應(yīng)用于Concurrency
Task {
    print("start task...")

    // Swift5.7之后,Swift5.9之前
    try await Task.sleep(until: .now + .seconds(1), clock: .suspending)
    // Swift5.9之后
    try await Task.sleep(for: .seconds(1), clock: .suspending)

    print("continue task...")
}

// 異步函數(shù)
func doSomeAsyncWork() async throws {
    print("start to work...")
    // Swift5.7之后,Swift5.9之前
    try await Task.sleep(until: .now + .seconds(3), clock: .continuous)
    // Swift5.9之后
    try await Task.sleep(for: .seconds(3), clock: .continuous)

    print("continue to work...")
}

Macros

介紹

  • Swift 5.9 引入了一個(gè)重要新功能 — 宏。
  • 宏可以在編譯前動(dòng)態(tài)地操作代碼,從而能夠在編譯時(shí)注入額外的功能。

分類

  • 獨(dú)立 Macro:通過@freestanding關(guān)鍵字聲明,使用時(shí)以標(biāo)簽#開頭,并在后邊的()中添加對(duì)應(yīng)的參數(shù),主要作用是代替代碼中的內(nèi)容。
  • 附加 Macro:通過@attached關(guān)鍵字聲明,使用時(shí)以標(biāo)簽@開頭,并在后邊的()中添加對(duì)應(yīng)的參數(shù),主要作用是為聲明添加代碼。

使用步驟

  1. 每個(gè) Macro 都是 Package,因此需要通過 Xcode 菜單 —> File —> New —> Package... —> Swift Macro 創(chuàng)建 Macro Package。
  2. Sources:源碼目錄包含 3 個(gè)子文件夾。
    • [Macro name]:包含創(chuàng)建 Macro 的聲明源文件。
    • [Macro name]Client:包含創(chuàng)建 Macro 的使用源文件。
    • [Macro name]Macros:包含創(chuàng)建 Macro 的實(shí)現(xiàn)源文件。
  3. 在使用 Macro 的地方,可以通過選中宏 —> 右鍵菜單 —> Expand Macro 在下方顯示展開后的代碼。
// 聲明源文件 [Macro name].swift
// 定義一個(gè)宏函數(shù),接收一個(gè)泛型參數(shù),返回原始值與對(duì)應(yīng)字符串組成的元組,函數(shù)實(shí)現(xiàn)在FirstMacroMacros的StringifyMacro
@freestanding(expression)
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "FirstMacroMacros",
                                                                      type: "StringifyMacro")

// 實(shí)現(xiàn)源文件 [Macro name]Macro.swift
public struct StringifyMacro: ExpressionMacro {
    public static func expansion(
        of node: some FreestandingMacroExpansionSyntax,
        in context: some MacroExpansionContext
    ) -> ExprSyntax {
        guard let argument = node.argumentList.first?.expression else {
            fatalError("compiler bug: the macro does not have any arguments")
        }

        return "(\(argument), \(literal: argument.description))"
    }
}
// 導(dǎo)出Macro以供使用
@main
struct FirstMacroPlugin: CompilerPlugin {
    let providingMacros: [Macro.Type] = [
        StringifyMacro.self,
    ]
}


// 使用源文件 main.swift
import FirstMacro

let a = 10
let b = 20
let (result, code) = #stringify(a + b)
print("The value \(result) was produced by the code \"\(code)\"")
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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