我需要在几个地方将相同的数据格式化为人类可读的格式。但是,我有几个框架以不同的方式表示这些信息。为避免重复此代码,我有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中NSFoundation
和Foundation
之间的Objective-C桥接问题。
我的方法是否存在问题,或者这是Swift中的错误?如果是后者,我会提交雷达。