Swift 5.0 值得关注的特性:增加 Result 枚举类型

栏目: Swift · 发布时间: 7年前

内容简介:HackingSwift: What’s new in Swift 5.0Result背景

HackingSwift: What’s new in Swift 5.0

Result 还是 Result

背景

在异步获取数据的场景中,常见的回调的数据结构是这样的:表示获取成功的数据,表示获取失败的 error。因为数据可能获取成功,也可能失败。因此回调中的数据和错误都是 optional 类型。

比如 CloudKit 中保存数据的一个函数就是这样:

func save(_ record: CKRecord, completionHandler: @escaping (CKRecord?, Error?) -> Void)

这种形式的缺点是没有体现出两种结果的互斥关系:如果数据成功获取到了,那么 error 一定为空。如果 error 有值,数据一定是获取失败了。

Swift 中枚举的能力相比 OC 有着很大的进步,每个枚举值除了可以是常规的基础类型,还可以是一个关联的类型。有了这样的特性后用枚举来优化返回结果的数据结构显得水到渠成:

enum Result
<success nbsp="" failure="">
  where Failure : Error {

    /// A success, storing a `Success` value.
    case success(Success)
    
    /// A failure, storing a `Failure` value.
    case failure(Failure)
}
</success>

基本用法

定义异步返回结果是 Int 类型的函数:

func fetchData(_ completionHandler: @escaping (Result
<int nbsp="" 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))
        }
    }
}
</int>

返回值的类型通过泛型进行约束,Result 第一个泛型类型表示返回值的类型,第二个类型表示错误的类型。对 Result  赋值和常规的枚举一样:

let valueResult: Result
<int nbsp="" customerror="">
  = Result.success(4)

// 因为 swift 中会进行类型推断,编译器在确认返回的是 `Result` 类型后,可以省略枚举类型的声明
let errorResult = .failure(CustomError.inputNotValid)
</int>

取出 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 nbsp="" error="">
  = Result.success(4)
let stringResult = x.map { (value) -> Result
 <string nbsp="" error="">
   in
    return  .success("map")
}

let originError = NSError(domain: "origin error", code: -1, userInfo: nil)
let errorResult: Result
  <int nbsp="" error="">
    = .failure(originError)
let newErrorResult = errorResult.mapError { (error) -> Error in
    let newError = NSError(domain: "new error", code: -2, userInfo: nil)
    return newError
}
  </int>
 </string>
</int>

flatMap、flatMapError

map 返回的是具体的结果和错误, flatMap 闭包中返回的是 Result 类型。如果 Result 中包含的是数据,效果和 map 一致,替换数据;如果 Result 中包含的是错误,那么不替换结果。

let intResult: Result
<int nbsp="" error="">
  = Result.success(4)

// 替换成功
let flatMapResult = intResult.flatMap { (value) -> Result
 <string nbsp="" error="">
   in
    return  .success("flatMap")
}

// 没有执行替换操作,flatMapIntResult 值还是 intResult
let flatMapIntResult = intResult.flatMap { (value) -> Result
  <string nbsp="" error="">
    in
    return  .failure(NSError(domain: "origin error", code: -1, userInfo: nil))
}
  </string>
 </string>
</int>

get

很多时候只关心  Result 的值,Swift 提供了 get() 函数来便捷的直接获取值,需要注意的是这个函数被标记为 throws,使用时语句前需要加上 try:

let intResult: Result
<int nbsp="" error="">
  = Result.success(4)

let value = try? intResult.get()
</int>

可抛出异常的闭包初始化器

很多时候获取返回值的闭包中可能会发生异常代表获取失败的错误,基于这个场景 Swift 提供了一个可抛出异常的闭包初始化器:

enum CustomError: Error, Equatable {
    case inputNotValid
}

let fetchInt = { () -> Int in
    if true {
        return 4
    } else {
        throw CustomError.inputNotValid
    }
}

let result: Result
<int nbsp="" error="">
  = Result { try fetchInt() }
</int>

需要提醒是通过这种方式声明的 Result 的 error 类型只能是 Error,不能指定特定的 Error。

微博:@没故事的卓同学

掘金博客

如果想与我有更密切的交流也可以加入我的知识星球: iOS 程序员保护协会

作者:没故事的卓同学

链接:https://www.jianshu.com/p/a3712edc9367


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web Data Mining

Web Data Mining

Bing Liu / Springer / 2006-12-28 / USD 59.95

Web mining aims to discover useful information and knowledge from the Web hyperlink structure, page contents, and usage data. Although Web mining uses many conventional data mining techniques, it is n......一起来看看 《Web Data Mining》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具