Если да, есть ли какие-либо ключевые различия, которые иначе не присутствовали бы при использовании наблюдения значения ключа в Objective-C?
swift
key-value-observing
codeperson
источник
источник
.initial
. Для решения см. Здесь . Я настоятельно рекомендую посмотреть документы Apple . Он был недавно обновлен и содержит множество важных заметок. Также см. Другой ответОтветы:
(Отредактировано, чтобы добавить новую информацию): подумайте, может ли использование Combine Framework помочь вам достичь того, что вы хотели, вместо использования KVO
Да и нет. KVO работает на подклассах NSObject так же, как всегда. Это не работает для классов, которые не подкласс NSObject. Swift не имеет (в настоящее время по крайней мере) собственной системы наблюдения.
(См. Комментарии о том, как выставить другие свойства как ObjC, чтобы KVO работал с ними)
См. Документацию Apple для полного примера.
источник
dynamic
ключевое слово в любом классе Swift для включения поддержки KVO.dynamic
ключевое слово относится к свойству, которое вы хотите сделать наблюдаемым по значению ключа.dynamic
ключевого слова можно найти в разделе « Использование Swift с какао и Objective-C» в библиотеке разработчика Apple .dynamic
ключевое слово для любых свойств внутри класса, который вы хотите, чтобы он был KVO-совместимым (неdynamic
ключевое слово для самого класса). Это сработало для меня!Вы можете использовать KVO в Swift, но только для
dynamic
свойствNSObject
подкласса. Учтите, что вы хотели наблюдать заbar
свойствомFoo
класса. В Swift 4 укажитеbar
какdynamic
свойство в своемNSObject
подклассе:Затем вы можете зарегистрироваться, чтобы наблюдать за изменениями в
bar
собственности. В Swift 4 и Swift 3.2 это было значительно упрощено, как описано в разделе Использование наблюдения значения ключа в Swift :Обратите внимание, что в Swift 4 теперь мы имеем строгую типизацию путей к ключам с использованием символа обратной косой черты (
\.bar
это путь к ключу дляbar
свойства наблюдаемого объекта). Кроме того, поскольку он использует шаблон закрытия завершения, нам не нужно вручную удалять наблюдателей (когдаtoken
выпадет из области видимости, наблюдатель удаляется для нас), а также нам не нужно беспокоиться о вызовеsuper
реализации, если ключ не соответствие. Закрытие вызывается только тогда, когда вызывается этот конкретный наблюдатель. Для получения дополнительной информации см. Видео WWDC 2017, Что нового в Foundation .В Swift 3 наблюдать это немного сложнее, но очень похоже на то, что делают в Objective-C. А именно, вы бы реализовали,
observeValue(forKeyPath keyPath:, of object:, change:, context:)
что (а) гарантирует, что мы имеем дело с нашим контекстом (а не с тем, что нашsuper
экземпляр зарегистрировал для наблюдения); а затем (b) либо обработать его, либо передать егоsuper
реализации, если необходимо. И обязательно удалите себя в качестве наблюдателя, когда это уместно. Например, вы можете удалить наблюдателя, когда он освобожден:В Swift 3:
Обратите внимание, что вы можете наблюдать только те свойства, которые могут быть представлены в Objective-C. Таким образом, вы не можете наблюдать дженерики,
struct
типы Swift,enum
типы Swift и т. Д.Для обсуждения реализации Swift 2, см. Мой оригинальный ответ ниже.
Использование
dynamic
ключевого слова для достижения KVO сNSObject
подклассами описано в разделе « Наблюдение значения ключа » главы « Принятие конвенций проектирования какао» руководства « Использование Swift с какао и Objective-C» :[Обратите внимание, что это обсуждение KVO было впоследствии удалено из руководства по использованию Swift с какао и Objective-C , которое было адаптировано для Swift 3, но оно все еще работает, как описано в верхней части этого ответа.]
Стоит отметить , что Swift имеет свою собственную родной наблюдателя свойство системы, но для класса указав свой собственный код , который будет выполняться при наблюдении его собственных свойств. KVO, с другой стороны, предназначен для регистрации, чтобы наблюдать изменения некоторых динамических свойств некоторого другого класса.
источник
myContext
и как вы наблюдаете несколько свойств?context
указатель.context
Указатель предоставляется наблюдателю приobserveValueForKeyPath:ofObject:change:context:
его вызове.context
Указатель может быть указателем C или ссылкой на объект.context
Указатель может быть используется в качестве уникального идентификатора для определения наблюдаемого изменения или для предоставления некоторых других данных наблюдателю ".options
пустым, это просто означает, что оноchange
не будет включать старое или новое значение (например, вы можете просто получить новое значение, ссылаясь на сам объект). Если вы просто укажете.new
и нет.old
, этоchange
будет означать, что в него будет входить только новое значение, но не старое значение (например, вам часто не важно, какое было старое значение, а только новое значение). Если вам нужноobserveValueForKeyPath
передать вам как старое, так и новое значение, укажите[.new, .old]
. Итог,options
просто указывает, что входит вchange
словарь.И да, и нет:
Да , вы можете использовать те же старые API KVO в Swift для наблюдения за объектами Objective-C.
Вы также можете наблюдать
dynamic
свойства объектов Swift, наследуемых отNSObject
.Но ... Нет, он не слишком типизирован, как можно было ожидать от системы наблюдения Swift.
Использование Swift с какао и Objective-C | Наблюдение за ключевыми значениями
Нет , в настоящее время нет встроенной системы наблюдения значений для произвольных объектов Swift.
Да , есть встроенные Обозреватели Собственности , которые строго типизированы.
Но ... Нет, они не являются KVO, так как они позволяют только наблюдать за собственными свойствами объектов, не поддерживают вложенные наблюдения ("ключевые пути"), и вы должны явно их реализовать.
Язык программирования Swift | Наблюдатели за недвижимостью
Да , вы можете реализовать явное наблюдение за значениями, которое будет строго типизировано, и позволять добавлять несколько обработчиков из других объектов и даже поддерживать вложение / "ключевые пути".
Но ... Нет, это не будет KVO, так как он будет работать только для свойств, которые вы реализуете как наблюдаемые.
Вы можете найти библиотеку для реализации таких наблюдений за ценностями здесь:
Observable-Swift - KVO для Swift - Наблюдение за ценностями и события
источник
Пример может помочь немного здесь. Если у меня есть экземпляр
model
классаModel
с атрибутами,name
иstate
я могу наблюдать эти атрибуты с:Изменения этих свойств приведут к вызову:
источник
Да.
KVO требует динамической отправки, поэтому вам просто нужно добавить
dynamic
модификатор в метод, свойство, индекс или инициализатор:dynamic var foo = 0
В
dynamic
Модификатор гарантирует , что ссылки на декларации будут динамически отправляемые и доступны черезobjc_msgSend
.источник
В дополнение к ответу Роба. Этот класс должен наследоваться
NSObject
, и у нас есть 3 способа вызвать изменение свойстваИспользовать
setValue(value: AnyObject?, forKey key: String)
изNSKeyValueCoding
Используйте
willChangeValueForKey
иdidChangeValueForKey
отNSKeyValueObserving
Использование
dynamic
. См. Swift Type СовместимостьИ свойство getter и setter вызывается при использовании. Вы можете проверить при работе с КВО. Это пример вычисляемого свойства
источник
обзор
Возможно использование
Combine
без использованияNSObject
илиObjective-C
Наличие:
iOS 13.0+
,macOS 10.15+
,tvOS 13.0+
,watchOS 6.0+
,Mac Catalyst 13.0+
,Xcode 11.0+
Примечание. Необходимо использовать только с классами, а не с типами значений.
Код:
Swift Версия: 5.1.2
Вывод:
См:
источник
В настоящее время Swift не поддерживает какой-либо встроенный механизм для наблюдения за изменениями свойств объектов, кроме 'self', поэтому нет, он не поддерживает KVO.
Тем не менее, KVO является настолько фундаментальной частью Objective-C и Cocoa, что кажется весьма вероятным, что он будет добавлен в будущем. Текущая документация, кажется, подразумевает это:
Использование Swift с какао и Objective-C
источник
Важно отметить, что после обновления Xcode до 7 beta вы можете получить следующее сообщение: «Метод не переопределяет ни один метод из своего суперкласса» . Это из-за необязательности аргументов. Убедитесь, что ваш обработчик наблюдения выглядит точно так:
источник
Это может оказаться полезным для немногих людей -
Я использовал KVO таким образом в Swift 3. Вы можете использовать этот код с небольшими изменениями.
источник
Еще один пример для тех, кто сталкивается с проблемой таких типов, как Int? а CGFloat? Вы просто устанавливаете свой класс как подкласс NSObject и объявляете свои переменные следующим образом, например:
источник