Swift 4:使用抛出型完成闭包处理错误时传参报错,如何修复?
修复抛出型闭包的编译器错误
首先得说清楚你遇到的问题根源:你定义的completion是一个不需要任何参数、但执行时可能抛出错误的闭包(类型是() throws -> Void)。但你现在调用它的时候,传了一个{ throw RefreshTokenError.notFounded }的闭包作为参数——这完全不符合completion的参数要求,它根本不需要参数,所以编译器才会报错“Argument passed to call that takes no arguments”。
下面给你三种可行的修复方案,你可以根据自己的需求选择:
方案1:改用接收错误的闭包(最常用的异步错误处理方式)
这种方式把completion改成接收可选Error参数,有错误就传错误实例,没错误传nil,逻辑清晰且适合异步场景:
private func executeRefreshTokenRequest(_ completion: @escaping (Error?) -> Void) { DispatchQueue.global(qos: .userInitiated).sync { guard let refreshToken = currentRefreshToken else { completion(RefreshTokenError.notFounded) // 直接传入错误 return // 记得加return,避免后续代码继续执行 } // 这里写你的refreshTokenUrlRequest逻辑... // 请求成功时调用 completion(nil) // 请求失败时调用 completion(对应的错误实例) } } // 调用示例 executeRefreshTokenRequest { error in if let error = error { print("刷新Token失败:\(error.localizedDescription)") } else { print("Token刷新成功") } }
方案2:使用Swift的Result类型(现代推荐写法)
Result类型可以明确区分成功和失败状态,代码可读性更强:
private func executeRefreshTokenRequest(_ completion: @escaping (Result<Void, Error>) -> Void) { DispatchQueue.global(qos: .userInitiated).sync { guard let refreshToken = currentRefreshToken else { completion(.failure(RefreshTokenError.notFounded)) return } // 后续的refreshTokenUrlRequest逻辑... // 成功时调用 completion(.success(())) // 失败时调用 completion(.failure(请求错误)) } } // 调用示例 executeRefreshTokenRequest { result in switch result { case .success: print("Token刷新成功") case .failure(let error): print("刷新失败:\(error)") } }
方案3:坚持使用抛出型闭包(仅适合同步场景)
如果你一定要保留() throws -> Void类型的completion,那得调整调用逻辑——因为这种闭包的含义是「闭包自身执行时可能抛出错误」,而不是「接收一个错误参数」。你需要直接在合适的上下文抛出错误,并且用try调用completion:
private func executeRefreshTokenRequest(_ completion: @escaping () throws -> Void) throws { try DispatchQueue.global(qos: .userInitiated).sync { guard let refreshToken = currentRefreshToken else { throw RefreshTokenError.notFounded // 直接抛出错误 } // 后续请求逻辑... try completion() // 成功时执行completion } } // 调用示例 do { try executeRefreshTokenRequest { print("Token刷新成功") } } catch { print("刷新失败:\(error)") }
⚠️ 注意:这种抛出型的写法在异步场景下(比如用async代替sync)会有问题,因为抛出的错误无法跨线程传递,所以更推荐前两种方案。
内容的提问来源于stack exchange,提问作者Drugan
相关产品推荐
相关产品推荐

