Почему я не могу объявить динамическую переменную внутри протокола - PullRequest
0 голосов
/ 09 января 2019

В настоящее время я работаю над протоколами для моих объектов, которые наследуются от Realm's Object. Внутри моих объектов у меня есть переменные, и эти переменные помечены как @objc dynamic

@objc dynamic var title: String = ""

Теперь представьте ситуацию, когда у меня больше похожих объектов с одинаковой переменной title. Я хочу создать для них протокол, так как хочу иметь только один универсальный метод для изменения заголовка объекта.

Итак, я создал протокол с переменной title, помеченной как @objc dynamic, ожидая, что так оно и будет

protocol Titleable: class {
    @objc dynamic var title: String { get set }
}

... это не сработало, и я получил две ошибки.

Один о маркировке переменной как @objc

@ objc может использоваться только с членами классов, протоколами @objc и конкретными расширениями классов

... это я мог бы решить, пометив протокол как @objc.

Однако у меня все еще была ошибка, связанная с ключевым словом dynamic

Только члены классов могут быть динамическими

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

Я как-то решил это, удалив @objc, а также dynamic ключевые слова

protocol Titleable: class {
    var title: String { get set }
}

... это работает. Я могу пометить переменную как @objc dynamic в классе, где я реализую этот протокол.

class Item: Object, Titleable {
    @objc dynamic var title: String = ""
}

Однако я не уверен, почему это работает и почему маркировка переменной как dynamic в объявлении протокола не работает. Буду признателен за любое объяснение.

1 Ответ

0 голосов
/ 09 января 2019

Посмотрите, что означает dynamic :

динамический

Примените этот модификатор к любому представителю класса, который может быть представлен по Objective-C. Когда вы помечаете объявление члена динамическим модификатор, доступ к этому члену всегда динамически отправляется с помощью время выполнения Objective-C. Доступ к этому члену никогда не является встроенным или девиртуализирован компилятором.

Поскольку объявления, отмеченные динамическим модификатором, отправляются используя среду выполнения Objective C, они должны быть помечены атрибут.

Особенно рассмотрим этот первый абзац. Это говорит о том, что что-то, помеченное dynamic, не может быть отправлено статически. Теперь рассмотрим случай, когда у меня есть некоторый класс в модуле. Он уже скомпилирован, и его методы были разосланы статически. Теперь рассмотрим другой модуль, который соответствует этому классу какому-либо протоколу, который включает метод dynamic. Как это может работать? Метод уже был статически отправлен в некоторых местах. Он не может быть задним числом преобразован в динамическую отправку. (То же самое может применяться к объявлениям в одном и том же модуле в зависимости от флагов компилятора и уровней доступа, но мне проще объяснить кросс-модуль.)

Основная причина, по которой вы хотите сделать это в любом случае, - убедиться, что вы можете использовать KVO для этого свойства. (Если у вас есть какая-то другая причина, по которой вам нужно заставить соответствующие типы использовать динамическое свойство, мне интересно узнать вариант использования.) Если это ваша цель, мне, вероятно, потребуется Titleable для соответствия NSObjectProtocol.

...