内容简介:在异步获取数据的场景中,常见的回调的数据结构是这样的:表示获取成功的数据,表示获取失败的 error。因为数据可能获取成功,也可能失败。因此回调中的数据和错误都是 optional 类型。 比如 CloudKit 中保存数据的一个函数就是这样:这种形式的缺点是没有体现出两种结果的互斥关系:如果数据成功获取到了,那么 error 一定为空。如果 error 有值,数据一定是获取失败了。Swift 中枚举的能力相比 OC 有着很大的进步,每个枚举值除了可以是常规的基础类型,还可以是一个关联的类型。有了这样的特性
在异步获取数据的场景中,常见的回调的数据结构是这样的:表示获取成功的数据,表示获取失败的 error。因为数据可能获取成功,也可能失败。因此回调中的数据和错误都是 optional 类型。 比如 CloudKit 中保存数据的一个函数就是这样:
func save(_ record: CKRecord, completionHandler: @escaping (CKRecord?, Error?) -> Void) 复制代码
这种形式的缺点是没有体现出两种结果的互斥关系:如果数据成功获取到了,那么 error 一定为空。如果 error 有值,数据一定是获取失败了。
Swift 中枚举的能力相比 OC 有着很大的进步,每个枚举值除了可以是常规的基础类型,还可以是一个关联的类型。有了这样的特性后用枚举来优化返回结果的数据结构显得水到渠成:
enum Result<Success, Failure> where Failure : Error {
/// A success, storing a `Success` value.
case success(Success)
/// A failure, storing a `Failure` value.
case failure(Failure)
}
复制代码
基本用法
定义异步返回结果是 Int 类型的函数:
func fetchData(_ completionHandler: @escaping (Result<Int, Error>) -> Void) {
DispatchQueue.global().async {
let isSuccess = true
if isSuccess {
let resultValue = 6
return completionHandler(.success(resultValue))
} else {
let error = NSError(domain: "custom error", code: -1, userInfo: nil)
return completionHandler(.failure(error))
}
}
}
复制代码
返回值的类型通过泛型进行约束, Result
第一个泛型类型表示返回值的类型,第二个类型表示错误的类型。对 Result
赋值和常规的枚举一样:
let valueResult: Result<Int, CustomError> = Result.success(4) // 因为 swift 中会进行类型推断,编译器在确认返回的是 `Result` 类型后,可以省略枚举类型的声明 let errorResult = .failure(CustomError.inputNotValid) 复制代码
取出 Result
值和获取普通的关联类型枚举是一样的:
fetchData { (result) in
switch result {
case .success(let value):
print(value)
case .failure(let error)
print(error.localizedDescription)
}
}
复制代码
如果你只想要获取其中一项的值,也可以直接用 if case 拆包:
fetchDate { (result) in
if case .success(let value) = result {
print(value)
}
}
复制代码
可以判等
Enum 是一个值类型,是一个值就应该可以判断是否相等。如果 Result
的成功和失败的类型都是 Equatable
,那么 Result
就可以判等,源码如下:
extension Result : Equatable where Success : Equatable, Failure : Equatable { }
复制代码
类似的,如果是成功和失败的类型都是 Hashable
,那么 Result
也是 Hashable
:
extension Result : Hashable where Success : Hashable, Failure : Hashable { }
复制代码
如果实现了 Hashable
,可以用来当做字典的 key。
辅助的 API
map、mapError
与 Dictionary 类似,Swift 为 Result
提供了几个 map value 和 error 的方法。
let intResult: Result<Int, Error> = Result.success(4)
let stringResult = x.map { (value) -> Result<String, Error> in
return .success("map")
}
let originError = NSError(domain: "origin error", code: -1, userInfo: nil)
let errorResult: Result<Int, Error> = .failure(originError)
let newErrorResult = errorResult.mapError { (error) -> Error in
let newError = NSError(domain: "new error", code: -2, userInfo: nil)
return newError
}
复制代码
flatMap、flatMapError
map 返回的是具体的结果和错误, flatMap 闭包中返回的是 Result
类型。如果 Result
中包含的是数据,效果和 map 一致,替换数据;如果 Result
中包含的是错误,那么不替换结果。
let intResult: Result<Int, Error> = Result.success(4)
// 替换成功
let flatMapResult = intResult.flatMap { (value) -> Result<String, Error> in
return .success("flatMap")
}
// 没有执行替换操作,flatMapIntResult 值还是 intResult
let flatMapIntResult = intResult.flatMap { (value) -> Result<String, Error> in
return .failure(NSError(domain: "origin error", code: -1, userInfo: nil))
}
复制代码
get
很多时候只关心 Result
的值,Swift 提供了 get()
函数来便捷的直接获取值,需要注意的是这个函数被标记为 throws
,使用时语句前需要加上 try
:
let intResult: Result<Int, Error> = Result.success(4) let value = try? intResult.get() 复制代码
可抛出异常的闭包初始化器
很多时候获取返回值的闭包中可能会发生异常代表获取失败的错误,基于这个场景 Swift 提供了一个可抛出异常的闭包初始化器:
enum CustomError: Error, Equatable {
case inputNotValid
}
let fetchInt = { () -> Int in
if true {
return 4
} else {
throw CustomError.inputNotValid
}
}
let result: Result<Int, Error> = Result { try fetchInt() }
复制代码
需要提醒是通过这种方式声明的 Result
的 error 类型只能是 Error
,不能指定特定的 Error
。
-
微博:(weibo.com/1926303682)
-
如果想与我有更密切的交流也可以加入我的知识星球:( t.zsxq.com/JEiqj27 )
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Swift 5.0 值得关注的特性:增加 Result 枚举类型
- c# – 枚举时项目发生变化时是否会影响枚举?
- 测者的测试技术手册:Junit单元测试遇见的一个枚举类型的坑(枚举类型详解)
- 测者的JUnit单元测试探坑记:Junit单元测试遇见的一个枚举类型的坑(枚举类型详解)
- c# – 循环枚举类型
- Python 的枚举类型
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Cracking the Coding Interview
Gayle Laakmann McDowell / CareerCup / 2015-7-1 / USD 39.95
Cracking the Coding Interview, 6th Edition is here to help you through this process, teaching you what you need to know and enabling you to perform at your very best. I've coached and interviewed hund......一起来看看 《Cracking the Coding Interview》 这本书的介绍吧!