微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Swift 5 的泛型方法中解开可选类型

如何解决在 Swift 5 的泛型方法中解开可选类型

我正在尝试从 B 类型的实例创建 A 类型的实例,但是原始类型 A 的某些属性是可选的,并且 B 的创建如果发生这种情况,{1}} 应该抛出错误

我的问题是我不知道 type T 是否是可选的,如果是,如何解开它。我正在尝试以下操作,但 swift 无法判断类型应该是什么...

下面的例子令人懊悔,真实样本几乎有一百个值。

struct A {
  let name: String?
  let price: Price?
  
  struct Price {
    let value: Double?
  }
}

struct B {
  let name: String
  let priceValue: Double
}

extension A {
  func convert() throws -> B {
    do {
      let name: String = try unwrap(\.name) // error: Type of expression is ambiguous without more context
      let priceValue: Double = try unwrap(\.price.value) // error: Type of expression is ambiguous without more context

      return B(name: name,priceValue: priceValue)
    }
  }

  func unwrap<U,T>(_ path: KeyPath<A,T>) throws -> U {

    let value = self[keyPath: path] // value is of type T

    if let value = value as? U {
      return value
    } else {
      throw Error.missing("KeyPath '\(path)' is 'nil'")
    }
  }

  enum Error: Swift.Error {
    case missing(String?)
  }
}

我知道以下内容可行,但我不想在代码中重复这 100 次?


extension A {
  func convertWithConditionals() throws -> B {
    do {
      guard let name = self.name else {
        throw Error.missing("KeyPath 'name' is 'nil'")
      }

      guard let priceValue = self.price?.value else {
        throw Error.missing("KeyPath 'price.value' is 'nil'")
      }
     
      return B(name: name,priceValue: priceValue)
    }
  }
}

一定有一些......快速的方式来做这件事,我没有想到。

解决方法

如果目的是仅使用通向可选属性的键路径调用 unwrap(),那么您可以将参数类型声明为 KeyPath<A,T?>,并且不需要第二个占位符类型 U :

func unwrap<T>(_ path: KeyPath<A,T?>) throws -> T {
    if let value = self[keyPath: path] {
        return value
    } else {
        throw Error.missing("KeyPath '\(path)' is 'nil'")
    }
}

用法可以简化为

func convert() throws -> B {
    let name = try unwrap(\.name)
    return B(name: name)
}

或者只是

func convert() throws -> B {
    return try B(name: unwrap(\.name))
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。