Joe's Blog

iOS 開發筆記

WWDC26 What's New in Swift

發佈於 2026-06-15

每年 WWDC 的 What’s New in Swift session 都是個節奏很快的大雜燴——語言改動、標準庫、效能、生態系全塞在一起。這篇只挑對 iOS 開發者日常最有感的部分。


🧹 日常語言改善

這類改動不會讓你的架構換血,但真的很煩的地方終於修了。

async 可以用在 defer 裡

1
2
3
4
5
6
7
8
9
// 以前這樣會編譯錯誤
defer {
    await cleanup()  // ❌
}

// 現在可以了
defer {
    await cleanup()  // ✅
}

做資源清理的時候(關 file handle、送 analytics event),cleanup 本身是 async 的,以前要繞很醜的路。現在直接支援。

weak let

1
2
3
4
5
// 以前只有 weak var
weak var delegate: MyDelegate?

// 現在可以用 weak let,能夠參與 Sendable 檢查
weak let delegate: MyDelegate?

weak var 因為可變,無法符合 Sendableweak let 解決了這個問題,在 Swift Concurrency 環境裡更安全地持有弱引用。

~Sendable 明確宣告

以前想讓某個 type「明確不是 Sendable」沒有好方法;現在可以直接標記 ~Sendable,不會影響到子類別的 conformance。


🌐 anyAppleOS

以前要標記「所有 Apple 平台」的 availability,要寫一長串:

1
2
@available(macOS 27, iOS 27, watchOS 27, tvOS 27, visionOS 27, *)
func showStatus() { ... }

現在一行搞定:

1
2
@available(anyAppleOS 27, *)
func showStatus() { ... }

Platforms State of the Union 也提到這個,但在 Swift session 裡有更完整的示範。對跨平台 framework 作者特別實用。


🎛️ @diagnose:細粒度的 warning 控制

有時候你用了某個被標記為 deprecated 的 API,但你有正當理由(等後端更新、或某個 workaround),又不想讓整個 build log 全是警告。

1
2
@diagnose(DeprecatedDeclaration, as: ignored, reason: "等後端 v3 API 部署後移除")
func fetchLegacyUserProfile() { ... }

可以把特定 warning 靜音、保留、或升格成 error,粒度到單一 function 或 property。比 #warning 更精準,也比 -Xswiftc -suppress-warnings 這種核彈選項文明多了。


🔗 Module Selectors(::

兩個 module 撞名的時候,以前只能靠 import alias 或重新命名;現在有明確的語法:

1
2
3
4
5
6
7
8
import ModuleA
import ModuleB

// 明確指定從哪個 module 拿
let x = ModuleA::SomeType()

// 方法也可以
object.ModuleB::doSomething()

大型專案引入多個 SPM 套件時偶爾會遇到命名衝突,這個語法讓衝突處理更直白。


📦 標準庫新成員

withTaskCancellationShield

Task 被取消後,cleanup 工作還是要跑完(例如寫完 log 再退):

1
2
3
4
5
func logout() async {
    await withTaskCancellationShield {
        await analyticsLogger.flush()  // task 取消也要跑完
    }
}

以前需要自己開一個新 Task 繞過取消;現在有正式 API。

Dictionary.mapKeyedValues

1
2
3
4
5
6
7
8
9
// 以前
let display = missions.reduce(into: [:]) { result, pair in
    result[pair.key] = makeDisplayName(for: pair.value, in: pair.key)
}

// 現在
let display = missions.mapKeyedValues { key, value in
    makeDisplayName(for: value, in: key)
}

mapValues 只能拿到 value;mapKeyedValues 同時拿 key 和 value,少一層 closure 煩惱。

FilePath

System 套件提供的跨平台路徑型別,告別字串拼接:

1
2
3
var path: FilePath = "/var/www/static"
path.components.append("WWDC")
// path == "/var/www/static/WWDC"

iOS 開發比較少直接操作 file path,但如果你有寫 CLI 工具或 Swift Package plugin,這個型別很好用。


⚡ 效能調校

@inline(always) 和 @specialized

兩個給進階使用者的屬性,讓你在需要時明確指示 compiler:

1
2
3
4
5
6
7
// 強制 inline,不讓 compiler 自己決定
@inline(always)
func criticalPath() { ... }

// 對特定型別生成特化版本,消除泛型開銷
@specialized(where T == [UInt8])
func process<T: Collection>(_ data: T) { ... }

一般 App 開發很少需要動到這層,但寫效能敏感的底層 library(例如 codec、parser)時很有用。

Noncopyable 型別的 protocol 支援

EquatableComparableHashable 現在支援 noncopyable 型別。如果你有在用 ~Copyable,這個改動讓你的型別能參與更多標準 protocol,不再需要自己重新實作比較邏輯。


🛠️ Subprocess 1.0

在 Swift 裡執行 shell command 終於有正式的 API(之前要用 Process,很囉嗦):

1
2
3
4
5
6
7
let result = try await Subprocess.run(
    .name("swiftformat"),
    arguments: ["Sources/"],
    output: .sequence
) { execution in
    execution.standardOutput.strings()
}

這對寫 Swift CLI 工具、Xcode Build Phase script 或 Package plugin 很實用。


🧩 Foundation 大搬家

Objective-C 寫的 Foundation 程式碼持續遷移到 Swift 實作,這次的亮點:

這些是底層改動,多數情況下你不需要改一行程式碼,但 App 的執行速度會悄悄變好。


💡 值得關注但相對進階

這幾個方向都很有趣,但對純 iOS 開發者來說暫時影響不大,知道有在走就好。


🔚 總結

Swift 6.4 的調性跟今年整體 WWDC 一樣務實:沒有語言哲學大轉向,但很多小地方確實更順手了。個人最有感的是 async deferanyAppleOSwithTaskCancellationShield 三個——都是以前要繞路或忍耐的地方,現在有了正確解法。


What’s New in Swift — WWDC26 Session 262


本文使用 Claude 共同完成