这是一个 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")
]
)