Swift 与 Objective-C

Swift throws 与 Result:保留失败原因的输入处理

比较try?合并成nil的两种错误,通过typed throws与Result保留原因,再用get取回成功值或重新抛出失败。

2 分钟阅读
Swift throws 与 Result:保留失败原因的输入处理 封面图

不同失败需要不同处理时,应该用throws或Result保留原因,而不是用try?抹去。throws沿调用流程传递错误;Result把成功或失败保存为值,供稍后处理。

原理与设计判断

ParseError区分非数字输入和负数。throws(ParseError)明确指定错误类型,do-catch即可据此选择响应。try?把两种失败都变成nil,当恢复策略不同时,这样的信息不够。 一手资料

复现代码

将cat、-1、0、42交给同一个解析器。先确认try?使两种失败都得到nil,再把结果保存为Result<Int, ParseError>。typed do代码块明确指定catch的错误类型,get则取回成功值或重新抛出失败。

这个独立示例已于 2026-10-23 使用 Apple Swift 6.4,以 Swift 6 语言模式在 arm64 macOS 目标环境运行。不需要网络或额外软件包。

下载完整 Swift 文件

请在下载文件的文件夹中运行。检查不通过时,precondition 会终止程序。请勿使用 -Ounchecked,因为它会移除这些检查。

swift -swift-version 6 swift-error-handling-throws-result.swift
enum ParseError: Error, Equatable { case notInteger, negative }
func parse(_ raw: String) throws(ParseError) -> Int {
    guard let value = Int(raw) else { throw .notInteger }
    guard value >= 0 else { throw .negative }
    return value
}

precondition((try? parse("cat")) == nil && (try? parse("-1")) == nil)
let results: [Result<Int, ParseError>] = ["cat", "-1", "0", "42"].map { raw in
    do throws(ParseError) { return .success(try parse(raw)) }
    catch { return .failure(error) }
}
precondition(results == [.failure(.notInteger), .failure(.negative), .success(0), .success(42)])
do {
    _ = try results[1].get()
    preconditionFailure("failure was lost")
} catch ParseError.negative {}
let recovered = try results[3].get()
precondition(recovered == 42)
print("try?-failures=nil,nil result=notInteger,negative,0,42 get-error=negative")

运行结果与解读

try?-failures=nil,nil result=notInteger,negative,0,42 get-error=negative

结果数组分别保留notInteger、negative、0、42。对失败结果调用get会再次抛出negative,成功结果则得到42。这项错误信息保留验证不需要网络或文件I/O。

适用范围与限制

throws不能捕获所有程序失败。强制解包或precondition违反造成的陷阱不在此契约内,try!失败也不应作为正常恢复路径。本实验只运行同步解析,未验证异步取消、重试或文件错误。

接下来要确认的事

根据调用方需要采取的不同行动定义错误。简单缺失值可用Optional;传递原因用throws;存储或汇总结果用Result。UI提示与日志适合在保留真实原因的边界接入。

延伸实验

来源与验证