Swift 6.1新特性学习

22 阅读3分钟

允许列表中的尾部逗号(SE-0439)

现在数组、字典、元组、函数调用、泛型参数、字符串插值以及由括号、方括号[]或尖括号约束的项目列表的任何位置都允许使用尾随逗号,提升多行代码的可维护性。

// 参数列表尾部逗号
func add<T: Numeric>(_ a: T, _ b: T,) -> T {
    a + b
}

// 数组尾部逗号
let numbers = [1, 2, 3,] 

应用场景:多行参数列表时,调整顺序或注释某行不会破坏语法:

message.range(
    of: "impossible",
    options: .caseInsensitive, // 注释此行无需删除逗号
)

元类型KeyPath(SE-0438)

KeyPath现在支持访问类型的静态属性。

struct WarpDrive {
    static let maxSpeed = 9.975  // 静态属性
    var currentSpeed = 8.0
}

// 访问实例属性
let currentSpeed = \WarpDrive.currentSpeed
// 访问静态属性的键路径
// KeyPath<WarpDrive.Type, Double>
let maxSpeedKeyPath = \WarpDrive.Type.maxSpeed
let specificType: KeyPath<WarpDrive.Type, Double> = .maxSpeed

任务组子任务结果类型推断(SE-0442)

withTaskGroup 和 withThrowingTaskGroup 可自动推断子任务返回类型,无需显式声明 of:

func fetchMessages() async -> String {
    await withTaskGroup { group in  // ✅ 无需 of: String.self
        group.addTask { "Hello" }
        group.addTask { "World" }

       var collected = [String]()
       for await value in group {
           collected.append(value)
       }

       return collected.joined(separator: " ")
    }
}

使用 nonisolated 避免全局 Actor 推断(SE-0449)

nonisolated 现可用于类型声明,避免从协议继承的全局 Actor 隔离。

@MainActor
protocol DataStoring { /* ... */ }

// 不使用`nonisolated`,App会默认继承MainActor,调用controller.load的时候不用写await
struct App: DataStoring {
    let controller = DataController()

    init() {
        controller.load()
    }
}

// 使用nonisolated之后,在调用Actor修饰的方法,就需要显示使用await
nonisolated struct App2: DataStoring {  // ✅ 退出主 Actor 隔离
    init() async {
        await controller.load()  // 需显式 await
    }
}

成员导入可见性(SE-0444)

模块的扩展成员不再隐式传递到其他文件,需显式导入。

问题示例
若 Maps 和 GeoKit 模块都扩展了 Double.toRadians(),旧版本可能导致冲突。
解决方案
在需要的文件中显式导入模块。并且开启MemberImportVisibility

编译器警告精细控制(SE-0443)

通过诊断组(Diagnostic Groups)控制特定警告的行为。

操作步骤

  1. 添加编译器标志 -print-diagnostic-groups
  2. 根据输出的诊断组名(如 [DeprecatedDeclaration])控制警告级别:
-Werror DeprecatedDeclaration  # 将弃用警告转为错误
-Wwarning=DeprecatedDeclaration  # 保持为警告(即使全局开启 Treat Warnings as Errors)

测试框架改进(ST-0005, ST-0006, ST-0007)

范围确认(ST-0005)

@Test func testNewsLoader() async {
    await confirmation(expectedCount: 5...10) { confirm in
        for await _ in NewsLoader() {
            confirm()  // 确认调用次数在 5-10 次之间
        }
    }
}

错误断言改进(ST-0006)

@Test func testPlayGame() {
    let error = #expect(throws: GameError.self) {
        try playGame(at: 22)
    }
    #expect(error == .disallowedTime)  // 直接验证错误类型
}

测试作用域(ST-0007)

struct PlayerTestTrait: TestScoping {
    func provideScope(/*...*/) async throws {
        try await Player.$current.withValue(customPlayer) {
            try await function()  // 在此作用域内运行测试
        }
    }
}

@Test(.playerTestTrait) func testCustomPlayer() { /* ... */ }

其他改进

  • 跨平台编译优化(SE-0387) :简化跨平台编译(如 Apple Silicon 编译 x86 Linux 程序)。
  • Objective-C 实现替换(SE-0436) :允许 Swift 覆盖 Objective-C 方法实现。
  • 包管理器可选特性(SE-0450) :包可声明可选特性(如实验性 API),使用者按需启用。

总结

Swift 6.1 主要聚焦于语法便利性(尾部逗号、类型推断)、并发安全(nonisolated)、模块可见性、测试框架增强和编译器控制。虽然无重大变革,但多项改进显著提升开发体验,为 Swift 6.2 的更大更新奠定基础。

资料参考

  1. www.hackingwithswift.com/articles/27…