J'ai essayé de trouver un exemple, mais ce que j'ai vu ne fonctionne pas dans mon cas.
Quel serait l'équivalent du code suivant:
object.addObserver(self, forKeyPath: "keyPath", options: [.new], context: nil)
override public func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
}
Le code ci-dessus fonctionne, mais je reçois un avertissement de SwiftLink:
Préférez la nouvelle API KVO basée sur des blocs avec des raccourcis clavier lorsque vous utilisez Swift 3.2 ou une version ultérieure).
Je l'apprécie si vous pouvez me diriger dans la bonne direction.
Swift 4 a introduit une famille de béton types de chemin-clé , un nouveau expression de chemin-clé pour les produire et une nouvelle fonction observer basée sur la fermeture disponible pour les classes qui héritent de NSObject
.
En utilisant ce nouvel ensemble de fonctionnalités, votre exemple particulier peut maintenant être exprimé de manière beaucoup plus succincte:
self.observation = object.observe(\.keyPath) {
[unowned self] object, change in
self.someFunction()
}
Types impliqués
observation:
NSKeyValueObservation
change:
NSKeyValueObservedChange
\.keyPath
: Une instance d'une classe KeyPath produite au moment de la compilation.Grammaire clé-chemin
Le général grammaire d'une expression de chemin d'accès au clé se présente sous la forme \Type.keyPath
Où Type
est un nom de type concret (y compris tous les paramètres génériques), et keyPath
une chaîne d'une ou plusieurs propriétés, des indices, ou des correctifs facultatifs de chaînage/décompression forcée. De plus, si le type de keyPath peut être déduit du contexte, il peut être éludé, ce qui donne un résultat extrêmement pithy \.keyPath
.
Ce sont toutes des expressions de chemin de clé valides:
\SomeStruct.someValue
\.someClassProperty
\.someInstance.someInnerProperty
\[Int].[1]
\[String].first?.count
\[SomeHashable: [Int]].["aStringLiteral, literally"]!.count.bitWidth
Propriété
Vous êtes le propriétaire de l'instance NSKeyValueObservation
que la fonction observe
renvoie, ce qui signifie que vous n'avez pas à le faireaddObserver
ni removeObserver
; vous gardez plutôt une référence forte à ce sujet aussi longtemps que vous avez besoin d'observer votre observation.
Vous êtes pas obligé de invalidate()
soit: ça va deinit
gracieusement. Vous pouvez donc le laisser vivre jusqu'à la disparition de l'instance qui le détient, l'arrêter manuellement en sélectionnant nil
de la référence ou même appeler invalidate()
si vous devez conserver votre instance en vie pour une raison quelconque.
Mises en garde
Comme vous l'avez peut-être remarqué, l'observation se cache toujours dans les limites du mécanisme KVO de Cocoa. Elle n'est donc disponible que pour les classes Obj-C et Swift classes héritant de NSObject
(chaque type préféré de Swift-dev) avec le exigence supplémentaire que toute valeur que vous souhaitez observer, doit être marquée comme @objc
(chaque attribut favori de Swift-dev) et déclarée dynamic
.
Cela étant dit, le mécanisme global est une amélioration bienvenue, en particulier parce qu'il parvient à observer rapidement les modules importés NSObjects
(il peut s'avérer nécessaire de les utiliser (par exemple, Foundation
) et sans affaiblir le pouvoir expressif que nous travaillons si durement pour obtenir à chaque frappe.
En note de bas de page, Key-Path Chaîne Expressions] sont toujours nécessaires pour accès dynamiqueNSObject
's propriétés de KVC ou appelez value(forKey(Path):)
Au-delà de KVO
Il y a beaucoup plus dans les expressions Key-Path que KVO. Les expressions \Type.path
Peuvent être stockées sous forme d'objets KeyPath
pour une utilisation ultérieure. Ils viennent dans des saveurs inscriptibles, partielles et effacées. Ils peuvent augmenter le pouvoir expressif des fonctions getter/setter conçues pour la composition, sans oublier le rôle qu’elles jouent en permettant aux plus forts estomacs de s’immerger dans le monde des concepts fonctionnels tels que les objectifs et les prismes. Je vous suggère de consulter les liens ci-dessous pour en savoir plus sur les nombreuses portes de développement qu'ils peuvent ouvrir.
Liens:
Expression du chemin clé @ docs.Swift.org
Proposition de Swift Evolution Smart KeyPaths
Le terrain de jeu Whats-new-in-Swift-4 d'Ole Begemann avec des exemples de Key-Path
Vidéo WWDC 2017: Quoi de neuf dans Foundation 4:35 pour SKP et 19:40 pour KVO.
Pour ajouter quelque chose à la réponse lorsque je rencontrais des problèmes sur mon application lorsque j'utilisais cette méthode dans iOS 10.
Dans iOS 10, vous devez toujours supprimer l'observateur avant de désallouer la classe, sinon vous obtiendrez un crash NSInternalInconsistencyException
indiquant que:
Une instance
A
de la classeC
a été désallouée alors que des observateurs de valeur clé étaient toujours enregistrés avec elle.
Pour éviter ce crash. Définissez simplement la propriété observateur que vous utilisez sur nil
.
deinit {
self.observation = nil
}