Создание подклассов Formatter для принятия Swift Structs в Swift 3.2 и более поздних версиях

Мне нужно отформатировать в нескольких местах один и тот же фрагмент данных в удобочитаемом формате. Тем не менее, у меня есть несколько структур, которые представляют эту информацию по-разному. Чтобы избежать дублирования этого кода, у меня есть 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,

Эти последние 2 пункта заставляют меня задуматься, не является ли это проблемой с мостом Objective-C между NSFoundation а также Foundation в Свифте.

Есть ли проблема с моей методологией здесь, или это ошибка в Swift? Если это последнее, я отправлю радар.

0 ответов

Другие вопросы по тегам