这是一个 Swift 微框架,提供 Result<Value, Error>。
Result<Value, Error> 的值可以是成功的(包装 Value)或者失败的(包装 Error)。这类似于 Swift 的原生 Optional 类型:success 类似于 some,而 failure 类似于 none,但带有关联的 Error 值。添加关联的 Error 允许传递错误以进行日志记录或向用户显示。
使用此微框架而不是自己编写 Result 类型,可以方便地与其他也使用 Result 的框架进行交互。
当操作有可能失败时,请使用 Result。考虑以下示例,该函数尝试从 JSON Dictionary 中提取给定键的 String。
typealias JSONObject = [String: Any]
enum JSONError: Error {
case noSuchKey(String)
case typeMismatch
}
func stringForKey(json: JSONObject, key: String) -> Result<String, JSONError> {
guard let value = json[key] else {
return .failure(.noSuchKey(key))
}
guard let value = value as? String else {
return .failure(.typeMismatch)
}
return .success(value)
}
此函数提供了对 Dictionary 提供的默认下标的更健壮的包装。它返回一个 Result,而不是返回 Any?,该 Result 要么包含给定键的 String 值,要么包含详细说明出错原因的 ErrorType。
处理 Result 的一种简单方法是使用 switch 语句对其进行解构。
switch stringForKey(json, key: "email") {
case let .success(email):
print("The email is \(email)")
case let .failure(.noSuchKey(key)):
print("\(key) is not a valid key")
case .failure(.typeMismatch):
print("Didn't have the right type")
}
使用 switch 语句可以进行强大的模式匹配,并确保涵盖所有可能的结果。 Swift 2.0 提供了新的方法来解构像 if-case 语句这样的枚举,但要注意,这种方法不能确保处理所有错误。
有关处理 Result 的其他可用方法,请参见 API 文档。
Swift 2.0 通过抛出和捕获 Error 引入了错误处理。 Result 通过封装结果而不是劫持控制流来实现相同的目标。 Result 抽象启用了强大的功能,例如 map 和 flatMap,使 Result 比 throw 更具可组合性。
由于处理抛出异常的 API 很常见,因此您可以使用 materialize 方法将此类函数转换为 Result。 相反,可以通过调用 dematerialize 来使用 Result 抛出错误。
map 和 flatMap 的操作方式与 Optional.map 和 Optional.flatMap 相同,只不过它们应用于 Result。
map 将 Result 转换为新类型的 Result。 它通过使用将 Value 类型转换为新值的函数来实现。 此转换仅在 success 的情况下应用。 在 failure 的情况下,关联的错误将重新包装在新 Result 中。
// transforms a Result<Int, JSONError> to a Result<String, JSONError>
let idResult = intForKey(json, key:"id").map { id in String(id) }
在此,最终结果要么是作为 String 的 id,要么从先前的结果中继承 failure。
flatMap 类似于 map,因为它将 Result 转换为另一个 Result。 但是,传递给 flatMap 的函数必须返回一个 Result。
深入讨论 map 和 flatMap 超出了本文档的范围。 如果您想更深入地了解,请阅读有关 functors 和 monads 的信息。 这篇文章是一个很好的 起点。
Result.xcodeproj 拖到您的项目或工作区中。Result.framework。pod 'Result', '~> 5.0'
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "MyProject",
targets: [],
dependencies: [
.package(url: "https://github.com/antitypical/Result.git",
from: "5.0.0")
]
)