Как составить быстрые свойства оболочки? - PullRequest
5 голосов
/ 14 января 2020

Я недавно экспериментировал с быстрыми оболочками свойств и задавался вопросом, существует ли какой-либо способ их объединения для достижения более модульной архитектуры. Например:

@WrapperOne @WrapperTwo var foo: T

Просмотр документации ничего не дал. Единственная ссылка на то, как это сделать, находится на этой странице GitHub (https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md) (цитаты ниже), которая, кажется, говорит, что это возможно. В других статьях говорилось, что их сложно составить, но не объяснялось, как это сделать. Тем не менее, я не могу понять, как это сделать, и был бы признателен, если бы кто-нибудь показал мне пример кода о том, как это реализовать (см. В нижней части поста).

Когда используются несколько оболочек свойств предусмотрены для данного свойства, обертки составлены вместе, чтобы получить оба эффекта. Например, рассмотрим состав DelayedMutable и Copying:

@DelayedMutable @Copying var path: UIBezierPath

Здесь у нас есть свойство, для которого мы можем отложить инициализацию до более позднего периода. Когда мы установим значение, оно будет скопировано с помощью NSCopying метода копирования. Композиция реализуется путем вложения более поздних типов оболочек в более ранние типы оболочек, где самый внутренний вложенный тип является типом исходного свойства. В приведенном выше примере базовое хранилище будет иметь тип DelayedMutable<Copying<UIBezierPath>>, а синтезированный метод получения / установки для пути будет просматривать оба уровня .wrappedValue:

private var _path: DelayedMutable<Copying<UIBezierPath>> = .init()
var path: UIBezierPath {
    get { return _path.wrappedValue.wrappedValue }
    set { _path.wrappedValue.wrappedValue = newValue }
}

Обратите внимание, что этот дизайн означает, что состав оболочки оболочки свойства не является коммутативным, поскольку порядок атрибутов влияет на способ выполнения вложения: @DelayedMutable @Copying var path1: UIBezierPath // _path1 имеет тип DelayedMutable> @Copying @DelayedMutable var path2: UIBezierPath // ошибка: _path2 имеет некорректно сформированный тип Копирование> В этом случае средство проверки типов предотвращает второе упорядочение, поскольку DelayedMutable не соответствует протоколу NSCopying. Это не всегда так: некоторые семантически плохие композиции не обязательно будут пойманы системой типов. Альтернативы этому подходу к композиции представлены в разделе «Рассматриваемые альтернативы».

В идеале я хотел бы реализовать что-то вроде следующего:

@propertyWrapper
struct Doubled {
    var number: Int
    var wrappedValue: Int {
        get { (value * 2) }
        set { value = Int(newValue / 2) }
    }
    init(wrappedValue: Int) {
        self.number = wrappedValue
    }
}

и

@propertyWrapper
struct Tripled {
    var number: Int
    var wrappedValue: Int {
        get { (value * 3) }
        set { value = Int(newValue / 3) }
    }
    init(wrappedValue: Int) {
        self.number = wrappedValue
    }
}

, чтобы это могло быть достигнуто:

@Tripled @Doubled var number = 5

Я понимаю, что этот пример является несколько глупой причиной для реализации композиции оболочки свойств, но это просто для простоты при изучении новой функции.

Любая помощь будет принята с благодарностью.

1 Ответ

3 голосов
/ 15 января 2020

Были некоторые проблемы с использованием нескольких оболочек свойств, так что часть функции была извлечена из Swift 5.1, но она будет доступна в 5.2. До этого вы не можете использовать несколько оберток свойств напрямую, как это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...