iOS extension Optional 可选类型的扩展

· IW扩展iOS · 4522字

扩展开源地址https://github.com/iWECon/IW
使用过程中有任何不适, 请及时发Issue告知
Code by iwe.
Thx.


前言

参考资料:https://appventure.me/2018/01/10/optional-extensions/

在看参考资料之前,我使用的可选项写起来超级复杂,看完之后实践了部分,让我的 Code 看起来更优美 ~

Optional 可选项作为 Swift 中一个非常重要的部分, 妥善运用, 能帮助我们有效的消除项目中的bug.
不过官方给出的可选类型 API 相当有限(如果我们忽略掉 customMirrordebugDescription, 那么他仅列出一对方法/属性).

var unsafelyUnwrapped: Wrapped { get } 
func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? 
func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?

尽管API的量非常有限, 但可选类型仍然非常有用, 因为Swift通过语法等功能弥补了它, 比如 optional chaining(可选链接)pattern matching(模式匹配), if letguard let.
然而, 在某些情况下, 会体现出不必要的干扰. 有时候, 一个非常简洁的方法可以让你用一行代码表示一个概念(代码块), 而不是多行组合的if let语句.

Emptiness

extension Optional {
    /// Returns true if the optional is empty.
    /// (如果可选值为空则返回true).
    var isNone: Bool {
        switch self {
        case .none: return true
        default: return false }
    }
    /// Returns true if the optional is not empty.
    /// (如果可选值不为空则返回true).
    var isSome: Bool {
        switch self {
        case .some(_): return true
        default: return false }
    }
}

这是可选类型最基本的补充. 实现也可以使用 switch 模式匹配, 但 nil 比较简短. Swift 4 中只能通过 siwtch 来实现. 它们将空选项的概念从代码中移除. 使用 optional.isSomeif optional == nil 比起来更简洁, 更少冗杂.

// 原始
guard leftButton != nil, rightButton != nil else { fatalError("Missing Interface Builder connections") }

// 优化
guard leftButton.isSome, rightButton.isSome else { fatalError("Missing Interface Builder connections") }

Or

extension Optional {
    /// Return the value of the Optional or the `default` parameter
    /// (若可选值为 nil, 则返回 default).
    /// - param: The value to return if the optional is empty
    func or(_ default: Wrapped) -> Wrapped {
        return self ?? `default`
    }

    /// Returns the unwrapped value of the optional *or*
    /// the result of an expression `else`
    /// I.e. optional.or(else: print("Arrr"))
    /// (若可选值为 nil, 则执行 else 获取返回内容).
    func or(else: @autoclosure () -> Wrapped) -> Wrapped {
        return self ?? `else`()
    }

    /// Returns the unwrapped value of the optional *or*
    /// the result of calling the closure `else`
    /// I.e. optional.or(else: { 
    /// ... do a lot of stuff
    /// })
    /// (若可选值为 nil, 则执行 else 获取返回内容).
    func or(else: () -> Wrapped) -> Wrapped {
        return self ?? `else`()
    }

    /// Returns the unwrapped contents of the optional if it is not empty
    /// If it is empty, throws exception `throw`
    /// (若可选值为 nil, 则返回一个Error).
    func or(throw exception: Error) throws -> Wrapped {
        guard let unwrapped = self else { throw exception }
        return unwrapped
    }
}

extension Optional where Wrapped == Error {
    /// Only perform `else` if the optional has a non-empty error value
    //// (Error 可选类型有值则返回 error 值, 否则执行 else).
    func or(_ else: (Error) -> Void) {
        guard let error = self else { return }
        `else`(error)
    }
}

isNone / isSome 的另一个概念是能够指定变量不成立时要执行的指令。这种语法能够让我们避免写出 if 或者 guard 分支,并且将逻辑编写成一个简单易懂的方法。

这个概念非常有用,它被定义在三个不同的函数中。

Default Value

首先,返回一个可选值或默认值:

let optional: Int? = nil
print(optional.or(10)) // 输出 10
Default Closure

其次,与第一个相似,不同的是它允许从闭包中返回一个默认值。

let secretValue = 5
let optional: Int? = nil
let unwrapped = optional.or(else: secretValue * 32) // unwrapped值 为 160 (5 * 32 = 160)

由于使用了 @autoclosure 闭锁参数,所以我们实际上可以只使用第二个or (也就是func or(else: @autoclosure () -> Wrapped) -> Wrapped) 实现。然后,使用一个默认值将自动转换为返回值的闭包。但是,我更喜欢有两个独立的实现,因为这样可以让用户使用更复杂的逻辑来编写闭包。

使用 @autoclosure 修饰的闭包,允许将默认值自动转化为闭包的返回值:
打个比方,有一个函数是这样的:
func callback(_ handler: () -> Bool) -> Void { }
它使用的时候是这样的:

callback({
    // 可以有一些更复杂的逻辑处理
    return true
})

当我们将 @autoclosure 加上的时候
func callback(_ handler:@autoclosure () -> Bool) -> Void { }
使用起来可以是这样的:
callback({ 3 > 5 })
这就是将默认值自动转化为返回值的闭包的意思
当然还有一些知识,阅读这篇文章:Swift 自动闭包(@autoclosure、@noescape、@escape)


Waiting...

回复