web-dev-qa-db-fra.com

Swift 4 pour observeValue (forKeyPath: ...)

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.

34
MXV

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

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.keyPathType 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

Docs KVO @ Apple

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.

76
Matias Pequeno

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 classe C 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
}    
6
barbarity