Subclassing Formatter接受Swift 3.2及更高版本中的Swift Structs

时间:2017-11-14 16:52:03

标签: objective-c swift swift3 foundation nsformatter

我需要在几个地方将相同的数据格式化为人类可读的格式。但是,我有几个框架以不同的方式表示这些信息。为避免重复此代码,我有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:)注释)
  • Widget成为class,以及符合WidgetRepresentable的内容。

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

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

0 个答案:

没有答案