1. throws:标记「可能出错」的函数
使用场景 :当一个函数 / 方法执行时可能失败(如网络请求、文件操作、数据解析),需要把错误传递给调用者 处理时,用 throws 标记函数。
Swift
// 1. 先定义错误类型(遵循 Error 协议)
enum NetworkError: Error {
case invalidURL // 无效 URL
case noData // 无数据返回
case decodingFailed // 数据解析失败
}
// 2. 用 throws 标记「可能出错」的函数
func fetchUserInfo(from urlString: String) throws -> [String: Any] {
// 模拟:检查 URL 是否有效
guard let url = URL(string: urlString) else {
// 出错时:用 throw 抛出错误(函数会立即终止,错误传递给调用者)
throw NetworkError.invalidURL
}
// 模拟:网络请求获取数据
let fakeData: Data? = nil // 假设请求失败,无数据
guard let data = fakeData else {
throw NetworkError.noData
}
// 模拟:解析数据
guard let json = try? JSONSerialization.jsonObject(with: data),
let userInfo = json as? [String: Any] else {
throw NetworkError.decodingFailed
}
// 成功时:返回结果
return userInfo
}
2. do/try/catch:立即捕获并处理错误
使用场景 :当你调用一个 throws 函数,想要就地处理错误 (比如给用户弹提示、回退操作)时,用 do/try/catch 包裹调用。
Swift
func showUserProfile() {
let urlString = "https://api.example.com/user"
// do 块:写可能出错的代码
do {
// try:标记调用 throws 函数的位置
let userInfo = try fetchUserInfo(from: urlString)
// 成功路径:更新 UI
print("获取用户信息成功:\(userInfo)")
}
// catch 块:捕获并处理错误(可以捕获特定错误,也可以捕获所有错误)
catch NetworkError.invalidURL {
print("错误:URL 无效,请检查地址")
} catch NetworkError.noData {
print("错误:网络请求无数据,请稍后重试")
} catch NetworkError.decodingFailed {
print("错误:数据解析失败")
} catch {
// 捕获其他未定义的错误(用 error 变量访问具体错误)
print("未知错误:\(error)")
}
}
// 调用测试
showUserProfile()
3. Result:封装「成功 / 失败」的结果(尤其适合异步)
使用场景:
- 异步操作 (如网络请求、耗时计算):因为异步函数没法直接用
throws传递错误,Result可以把「成功值」和「错误」封装成一个枚举,通过回调传递。 - 需要延迟处理错误 或把错误当值传递 / 存储时。
Swift
// 1. 模拟异步网络请求函数(用 Result 作为回调参数)
func asyncFetchUserInfo(
from urlString: String,
completion: @escaping (Result<[String: Any], NetworkError>) -> Void
) {
// 模拟异步延迟(比如网络请求耗时)
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
// 检查 URL
guard let _ = URL(string: urlString) else {
// 失败时:回调 .failure(错误)
completion(.failure(.invalidURL))
return
}
// 模拟成功返回数据
let fakeUserInfo: [String: Any] = ["name": "张三", "age": 20]
// 成功时:回调 .success(值)
completion(.success(fakeUserInfo))
}
}
// 2. 调用异步函数,用 switch 处理 Result
func loadUserAsync() {
print("开始异步请求...")
asyncFetchUserInfo(from: "https://api.example.com/user") { result in
// 用 switch 解包 Result(处理成功/失败两种情况)
switch result {
case .success(let userInfo):
// 成功路径:拿到值
print("异步请求成功:\(userInfo)")
case .failure(let error):
// 失败路径:拿到错误
print("异步请求失败:\(error)")
}
}
}
// 调用测试
loadUserAsync()
简单对比总结
| 方式 | 核心场景 | 特点 |
|---|---|---|
throws |
同步函数可能出错,需传递错误 | 轻量,错误直接向上传递 |
do/try/catch |
调用 throws 函数时就地处理错误 | 清晰分离成功 / 失败逻辑,可捕获特定错误 |
Result |
异步操作、需延迟 / 传递错误结果 | 把成功 / 失败封装成值,适合回调传递 |