Dans l'affirmative, existe-t-il des différences essentielles qui n'étaient pas présentes lors de l'utilisation de l'observation clé-valeur en Objective-C ?
Quel est le but de myContext
et comment observer des propriétés multiples ?
Dans l'affirmative, existe-t-il des différences essentielles qui n'étaient pas présentes lors de l'utilisation de l'observation clé-valeur en Objective-C ?
Vous pouvez utiliser KVO en Swift, mais seulement pour dynamic
les propriétés de NSObject
sous-classe. Considérons que vous vouliez observer le bar
d'un Foo
la classe. Dans Swift 4, spécifiez bar
como dynamic
dans votre NSObject
sous-classe :
class Foo: NSObject {
@objc dynamic var bar = 0
}
Vous pouvez alors vous inscrire pour observer les changements apportés au bar
propriété. Dans Swift 4 et Swift 3.2, cela a été grandement simplifié, comme indiqué dans Utilisation de l'observation clé-valeur en Swift :
class MyObject {
private var token: NSKeyValueObservation
var objectToObserve = Foo()
init() {
token = objectToObserve.observe(\.bar) { [weak self] object, change in // the `[weak self]` is to avoid strong reference cycle; obviously, if you don't reference `self` in the closure, then `[weak self]` is not needed
print("bar property is now \(object.bar)")
}
}
}
Notez que, dans Swift 4, nous disposons désormais d'une saisie forte des chemins de clés à l'aide du caractère backslash (la balise \.bar
est le chemin d'accès au bar
propriété de l'objet observé). De plus, parce qu'il utilise le modèle de fermeture de complétion, nous n'avons pas besoin de supprimer manuellement les observateurs (lorsque la fonction token
sort du champ d'application, l'observateur est supprimé pour nous) et nous n'avons pas non plus à nous soucier de l'appel de la fonction super
si la clé ne correspond pas. La fermeture est appelée uniquement lorsque cet observateur particulier est invoqué. Pour plus d'informations, voir la vidéo de la WWDC 2017, Quoi de neuf dans la Fondation .
Dans Swift 3, pour observer cela, c'est un peu plus compliqué, mais très similaire à ce que l'on fait en Objective-C. A savoir, vous implémentez observeValue(forKeyPath keyPath:, of object:, change:, context:)
ce qui permet (a) de s'assurer que nous traitons avec notre contexte (et non avec quelque chose que notre super
s'est inscrite pour l'observer) ; et ensuite (b) soit la traiter, soit la transmettre à l'instance de l super
la mise en œuvre, si nécessaire. Et assurez-vous de vous retirer en tant qu'observateur lorsque cela est approprié. Par exemple, vous pouvez retirer l'observateur lorsqu'il est désalloué :
Dans Swift 3 :
class MyObject: NSObject {
private var observerContext = 0
var objectToObserve = Foo()
override init() {
super.init()
objectToObserve.addObserver(self, forKeyPath: #keyPath(Foo.bar), options: [.new, .old], context: &observerContext)
}
deinit {
objectToObserve.removeObserver(self, forKeyPath: #keyPath(Foo.bar), context: &observerContext)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard context == &observerContext else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
// do something upon notification of the observed object
print("\(keyPath): \(change?[.newKey])")
}
}
Attention, vous ne pouvez observer que les propriétés qui peuvent être représentées en Objective-C. Ainsi, vous ne pouvez pas observer les génériques, Swift struct
types, Swift enum
types, etc.
Pour une discussion sur l'implémentation de Swift 2, voir ma réponse originale, ci-dessous.
Utilisation de la dynamic
mot-clé pour atteindre la KVO avec NSObject
est décrite dans le document Observation de la valeur d'une clé de la section Adopter les conventions de conception Cocoa chapitre du Utiliser Swift avec Cocoa et Objective-C guide :
L'observation clé-valeur est un mécanisme qui permet aux objets d'être informés des changements apportés à des propriétés spécifiques d'autres objets. Vous pouvez utiliser l'observation clé-valeur avec une classe Swift, à condition que celle-ci hérite de la classe
NSObject
classe. Vous pouvez utiliser ces trois étapes pour mettre en œuvre l'observation clé-valeur en Swift.
Ajouter le
dynamic
à toute propriété que vous souhaitez observer. Pour plus d'informations sur lesdynamic
voir Nécessité d'un dispatching dynamique .class MyObjectToObserve: NSObject { dynamic var myDate = NSDate() func updateDate() { myDate = NSDate() } }
Créer une variable contextuelle globale.
private var myContext = 0
Ajoutez un observateur pour le chemin de la clé, et remplacez la fonction
observeValueForKeyPath:ofObject:change:context:
et supprimer l'observateur dans la méthodedeinit
.class MyObserver: NSObject { var objectToObserve = MyObjectToObserve() override init() { super.init() objectToObserve.addObserver(self, forKeyPath: "myDate", options: .New, context: &myContext) } override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if context == &myContext { if let newValue = change?[NSKeyValueChangeNewKey] { print("Date changed: \(newValue)") } } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } } deinit { objectToObserve.removeObserver(self, forKeyPath: "myDate", context: &myContext) } }
[Note : cette discussion sur KVO a été retirée de la page d'accueil du site Web de la Commission européenne. Utiliser Swift avec Cocoa et Objective-C qui a été adapté pour Swift 3, mais qui fonctionne toujours comme indiqué en haut de cette réponse].
Il est intéressant de noter que Swift possède son propre système natif observateur immobilier mais c'est pour une classe qui spécifie son propre code qui sera exécuté lors de l'observation de ses propres propriétés. La KVO, en revanche, est conçue pour s'enregistrer afin d'observer les modifications apportées à une propriété dynamique d'une autre classe.
Selon Guide de programmation de KVO : " Lorsque vous enregistrez un objet en tant qu'observateur, vous pouvez également fournir un context
pointeur. Le site context
Le pointeur est fourni à l'observateur lorsque observeValueForKeyPath:ofObject:change:context:
est invoquée. Le site context
Le pointeur peut être un pointeur C ou une référence d'objet. Le site context
Le pointeur peut être utilisé comme un identifiant unique pour déterminer le changement observé ou pour fournir d'autres données à l'observateur."
(Modifié pour ajouter de nouvelles informations) : voyez si l'utilisation du cadre Combine peut vous aider à accomplir ce que vous voulez, plutôt que d'utiliser KVO.
Oui et non. La KVO fonctionne sur les sous-classes de NSObject comme elle l'a toujours fait. Il ne fonctionne pas pour les classes qui ne sous-classent pas NSObject. Swift ne dispose pas (du moins actuellement) de son propre système d'observation natif.
(Voir les commentaires pour savoir comment exposer d'autres propriétés en tant que ObjC afin que le KVO puisse travailler dessus).
Voir le Documentation Apple pour un exemple complet.
Pour info, j'ai rempli un rapport de bogue avec Apple à ce sujet. J'encourage tous les autres qui aimeraient voir un système d'observation KVO ou similaire dans swift, à faire de même.
Depuis Xcode 6 beta 5, vous pouvez utiliser la fonction dynamic
sur toute classe Swift pour activer le support KVO.
Hourra pour @fabb ! Pour plus de clarté, le dynamic
Le mot clé va sur la propriété que vous voulez rendre observable par une valeur clé.
A la fois oui et non :
Sí En effet, vous pouvez utiliser les mêmes vieilles API KVO en Swift pour observer les objets Objective-C.
Vous pouvez également observer dynamic
des propriétés des objets Swift héritant de NSObject
.
Mais... Non il n'est pas fortement typé comme on pourrait s'attendre à ce que le système d'observation natif de Swift le soit.
Utiliser Swift avec Cocoa et Objective-C | Observation des valeurs clés
Non Pour l'instant, il n'existe pas de système intégré d'observation des valeurs pour les objets arbitraires de Swift.
Sí il existe des modules intégrés Observateurs de la propriété qui sont fortement typés.
Mais... Non ils ne sont pas KVO, puisqu'ils ne permettent que l'observation des propriétés propres des objets, ne supportent pas les observations imbriquées ("key paths"), et vous devez les implémenter explicitement.
Le langage de programmation Swift - Observateurs de propriétés
Sí Dans le cas de l'observation des valeurs, vous pouvez mettre en œuvre une observation explicite des valeurs, qui sera fortement typée et permettra d'ajouter des gestionnaires multiples à partir d'autres objets, et même de prendre en charge l'imbrication et les "chemins de clés".
Mais... Non ce ne sera pas la KVO puisqu'elle ne fonctionnera que pour les propriétés que vous implémentez comme observables.
Vous trouverez ici une bibliothèque permettant de mettre en œuvre ce type d'observation des valeurs :
Observable-Swift - KVO pour Swift - Observation des valeurs et événements
Oui.
KVO nécessite une répartition dynamique, il suffit donc d'ajouter l'option dynamic
à une méthode, une propriété, un indice ou un initialisateur :
dynamic var foo = 0
El dynamic
garantit que les références à la déclaration seront distribuées de manière dynamique et accessibles par le biais de l'option objc_msgSend
.
Actuellement, Swift ne prend pas en charge de mécanisme intégré permettant d'observer les changements de propriété d'objets autres que le "soi", donc non, il ne prend pas en charge la KVO.
Cependant, KVO est un élément tellement fondamental d'Objective-C et de Cocoa qu'il semble tout à fait probable qu'il sera ajouté à l'avenir. La documentation actuelle semble le laisser entendre :
Observation de la valeur d'une clé
Informations à venir.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
Un projet d'exemple qui démontre l'utilisation de KVO dans une interface UIKit via Swift : github.com/jameswomack/kvo-in-swift
0 votes
@JanDvorak Voir le Guide de programmation de KVO qui constitue une bonne introduction au sujet.
1 votes
Bien que cela ne réponde pas à votre question, vous pouvez également lancer des actions en utilisant la fonction didset().
0 votes
Notez qu'il existe un Swift4 bug lorsque vous utilisez
.initial
. Pour une solution, voir ici . Je recommande vivement de voir Documents d'Apple . Il a été mis à jour récemment et couvre de nombreuses notes importantes. Voir également le document de Rob autre réponse