首页 > 解决方案 > 我怎样才能最好地在 Swift 中记录失败的演员表?

问题描述

如何以优雅的方式记录铸造失败?理想情况下,我很想做类似下面的事情,但由于Any无法扩展,我很茫然。我也不知道使用分配的类型(例如String.self)进行转换的方法,所以这是两个问题。

let actuallyADouble: Any = 3.0
let stringType = String.self
guard let anyToString = actuallyADouble as? stringType else {
    actuallyADouble.logFailedCast(to: stringType)
    return
}
setString(anyToString) // will never reach

对于奖励积分,更神奇的是扩展所有转换的方法,因此我可以执行以下操作,并且在失败时会在此范围之外出现日志:

guard let anyToString = actuallyADouble as? stringType else { return }

背景:

我们有一个 Swift 项目没有强制执行避免强制转换的做法,所以有很多这样的事情:

let anyToString = actuallyADouble as! String

我们正在重构这个更安全的代码:

guard let anyToString = actuallyADouble as? String else { return }

现在我们的应用程序不会崩溃,而是会继续运行,就像没有问题一样,这可能会使故障排除变得更加困难。

标签: swift

解决方案


正如你所说,扩展Any是不可能的。但是可选项包含任何内容,如果您依赖它们,您可以获得日志记录并拥有与您已经使用的代码非常相似的代码。

extension Optional {
  struct UnwrapError: Error { }

  static func unwrap(_ any: Any) throws -> Wrapped {
    guard let wrapped = any as? Wrapped else {
      print("\(any) cannot be cast to \(Wrapped.self)")
      throw UnwrapError()
    }

    return wrapped
  }
}
try Double?.unwrap(actuallyADouble) // 3
let double: Double = try Optional.unwrap(actuallyADouble) // 3
try? String?.unwrap(actuallyADouble) // nil. "3.0 cannot be cast to String"

……甚至只是

extension Optional {
  init(_ any: Any) {
    self = any as? Wrapped
    if self == nil {
      print("\(any) cannot be cast to \(Wrapped.self)")
    }
  }
}
Double?(actuallyADouble) // 3
String?(actuallyADouble) // nil. "3.0 cannot be cast to String"

推荐阅读