0

我需要在几个地方将同一条数据格式化为人类可读的格式。但是,我有几个框架以不同的方式表示这些信息。为避免重复此代码,我有一个Formatter用于格式化此数据的通用表示的方法。任何想要使用这种人类可读表示的框架都可以让他们的数据声明符合一个Protocol(通常在扩展中),将他们自己的表示转换Struct为格式化程序使用的通用表示。

这正如我在 Swift 3 中所期望的那样工作。但是,在 Swift 3.2 及更高版本中,向Protocol内部的强制转换string(for obj:)失败。我不知道这是故意的改变,还是一个错误。在这个例子中:

import Foundation

struct Widget {
    let frobberCount: Int
    let tweakerCount: Int
}

protocol WidgetRepresentable {
    var widgetRepresentation: Widget { get }
}

extension Widget: WidgetRepresentable {
    var widgetRepresentation: Widget {
        return self
    }
}

class WidgetFormatter: Formatter {
    override func string(for obj: Any?) -> String? {
        guard let widget = obj as? WidgetRepresentable else { // This cast fails
            return nil
        }

        return string(from: widget)
    }

    func string(from widgetRepresentable: WidgetRepresentable) -> String {
        let widget = widgetRepresentable.widgetRepresentation
        return "\(widget.frobberCount) frobber(s), \(widget.tweakerCount) tweaker(s)"
    }
}

let formatter = WidgetFormatter()
let widget = Widget(frobberCount: 2, tweakerCount: 4)

formatter.string(for: widget) // Returns nil. Expected 2 frobber(s), 4 tweaker(s)
formatter.string(from: widget) // Correctly returns 2 frobber(s), 4 tweaker(s)

作为一种解决方法,如果我执行以下任何操作,问题就会消失:

  • 使用便利string(from:)功能,而不是string(for:)Formatter.
  • WidgetFormatter不再有子类(从函数中Formatter删除override注释)string(for:)
  • Have Widgetbe a class,以及任何符合 的WidgetRepresentable

最后两点让我想知道这是否是Swift之间NSFoundation的Objective-C 桥接问题。Foundation

我的方法是否存在问题,或者这是 Swift 中的错误?如果是后者,我会归档雷达。

4

0 回答 0