【问题标题】:Swift Extension - OptionalSwift 扩展 - 可选
【发布时间】:2020-07-08 10:54:22
【问题描述】:

我正在尝试将可选项扩展为可读的内容,并且目前已实现:

@discardableResult
    func isNotNil(_ handler: (Wrapped) -> Void) -> Optional {
        switch self {
        case .some(let value):
            handler(value)
            return self
        case .none:
            return self
        }
    }
    
    @discardableResult
    func isNil(_ handler: () -> Void) -> Optional {
        switch self {
        case .some:
            return self
        case .none:
            handler()
            return self
        }
    }

这样我就可以在可选的函数上调用我的函数,例如:

viewModel?.title.isNotNil { _ in
   //do something
}.isNil {
  //handle error
}

问题是,我想重用这些函数来返回特定类型,但我无法实现或遗漏了一些东西。例如:

let vm: MyViewModel = dataSource?.heading.isNotNil {
  return MyViewModel(title: $0.title, subtitle: $0.subtitle)
}

我一直在集思广益,希望能得到一些帮助。

谢谢!

【问题讨论】:

  • 你在重新发明Optional.map吗?例如。 let vm = dataSource?.heading.map { MyViewModel(...) }

标签: swift swift-optionals


【解决方案1】:

Optional 是通用的,并且有一个关联类型,您也可以在扩展中使用它。它被称为Wrapped

以下是一些您可以粘贴到 Playground 中的示例代码:

import UIKit

extension Optional {
    @discardableResult
    func isNil(_ handler: () -> Void) -> Wrapped? { // <-- We are returning Wrapped, wich is a generic concrete type
        switch self {
        case .some:
            return self
        case .none:
            handler()
            return self
        }
    }
}

let str: String? = nil

// The function is used and the return value is assigned to the variable handled
let handled = str.isNil { 
    print("Handling nil value")
}

print(type(of: handled))
// Prints "Optional<String>

还请注意,您尝试构建的大部分内容已经存在:https://developer.apple.com/documentation/swift/optional/1539476-map

您可能应该只使用 Swift 的地图而不是您自己的实现。

【讨论】:

    【解决方案2】:

    您在示例中所做的操作会引发错误。归结为

    let vm: MyViewModel
    if let heading = dataSource?.heading  {
       _ = MyViewModel(heading.title, heading.subtitle)
      vm = heading
    }
    

    所以你试图将heading 分配给vm(我假设它们是不同的类型),你只需构造并删除你在闭包中构造的MyViewModel

    以下是更好的选择:

    func mapOptionalOrNot<T>(notNil: (Wrapped) -> T, isNil: () -> T) -> T {
        switch self {
        case .some(let value):
            return notNil(value)
        case .none:
            return isNil()
        }
    }
    

    当然你也可以给这两个函数提供默认参数,这样你就可以把它们排除在外。

    使用 Swift 5.3 的新多重闭包,您可以执行类似的操作

    let vm: MyViewModel = dataSource?.heading.mapOptionalOrNot { value in
        // Map if we have a value
        return MyViewModel(title: value.title, subtitle: value.subtitle)
    } isNil: {
        // Map if we don't have a value
        return MyViewModel(title: "Empty", subtitle: "Empty")
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多