// 1) 显式写 Void func sayHello() -> Void { print("Hello World!") } // 2) 用空元组 () 代替 Void func sayHello() -> () { print("Hello World!") } // 3) 直接省略返回箭头与类型(最常见) func sayHello() { print("Hello World!") } sayHello() // "Hello World!".Void 本质是 ()(空元组)的 typealias,所以 -> Void 和 -> () 是一回事。
.省略返回箭头是最常见的写法,说明“这个函数只做事,不给结果”。
.文档/教程/示例代码:有时我会刻意写 -> Void 来教学,降低初学者的理解负担。
func process(_ items: [Int]) { guard !items.isEmpty else { return } // ... 下面是正式逻辑 }这里的 return 只是终止,不携带值。
let work1: () -> Void = { print("done") } let work2: () -> () = { print("done") } let work3: () -> Void in // 不合法,必须写完整 // 正确的第三种:省略整个返回部分 let work3b: () -> Void = { print("done") }更常见的是带参数、无返回的场景:
let transform: (Int) -> Void = { value in print("value = \(value)") }Swift 的类型推断很聪明,但在闭包里省略返回类型容易让签名变得不直观,特别是多层泛型或异步回调时。我的经验是:
局部一次性闭包:交给类型推断,代码更短。
func refresh() async { // 异步刷新,无需返回值 } Task { await refresh() }如果你习惯在 Task {} 中写匿名闭包,也可以显式标注它是 () -> Void 的异步版本:
@MainActor func load() async -> Void { // 允许写 -> Void,但多数情况下直接省略 // ... }注意:async -> Void 与 async(省略返回)依旧等价;选择哪种仍然是“可读性优先”。
enum SaveError: Error { case diskFull } // 堆代码 duidaima.com func save(_ data: Data, completion: (Result<Void, SaveError>) -> Void) { let ok = Bool.random() if ok { completion(.success(())) } else { completion(.failure(.diskFull)) } }这里的 .success(()) 就是把“空元组”作为“成功但无数据”的语义承载体。Alamofire 也常用 Result<Void, Error> 表示“请求成功但无返回体”。
func test_save_emitsSuccess() { let exp = expectation(description: "save success") save(Data()) { result in if case .success = result { exp.fulfill() } } waitForExpectations(timeout: 1) }写在最后