2008-10-03 4 views
13

Je suis habitué à coder des interfaces Java Swing, et dans celles si vous avez des propriétés qui changent, et vous voulez que votre interface soit mise à jour, vous mettrait en œuvre le modèle observateur/observable. En Java, vous le faites normalement en demandant à votre classe de conserver une liste d'écouteurs qu'elle notifie de différents événements.Quelle est la meilleure façon de faire observateur/observable en objectif-c (version iphone)

J'ai joué avec Objective-C sur Mac, et cela a KVC et la liaison qui semble fonctionner très bien, et nécessite moins de code. Le SDK iPhone ne semble pas avoir cette fonctionnalité, donc ma question est: Si j'ai une classe qui contient des données qui changent, quelle est la meilleure façon pour moi d'enregistrer un composant d'interface utilisateur avec cette classe afin qu'il puisse être notifié des changements dans les données qu'il doit afficher?

Répondre

37

Il existe deux méthodes intégrées d'observation dans Cocoa: l'observation de valeurs-clés et les notifications. Dans aucun de ces systèmes, vous n'avez besoin de maintenir ou de notifier vous-même une collection d'observateurs; le cadre gérera cela pour vous. Key-Value Observing (KVO) vous permet d'observer une propriété d'un objet - y compris même une propriété qui représente une collection - et d'être informé des changements apportés à cette propriété. Vous avez juste besoin d'envoyer l'objet -addObserver:forKeyPath:options:context: en passant l'objet que vous souhaitez recevoir les mises à jour, le chemin clé de la propriété (par rapport au récepteur) pour lequel vous souhaitez recevoir des mises à jour, et les types de mises à jour que vous souhaitez recevoir. (Il existe des méthodes similaires que vous pouvez utiliser si vous souhaitez observer une propriété représentant une collection.)

Les notifications sont plus anciennes et plus lourdes. Vous enregistrez avec un NSNotificationCenter - généralement le centre par défaut - une paire d'objets et de sélecteurs pour recevoir une notification lorsqu'un événement se produit. L'objet de notification lui-même peut contenir des données arbitraires via sa propriété userInfo et vous pouvez choisir d'observer toutes les notifications d'un nom spécifique plutôt que celles qui s'appliquent à un objet particulier.

Lequel devriez-vous utiliser dans un cas particulier? En général, si vous vous souciez des modifications apportées à une propriété spécifique d'un objet spécifique, utilisez l'option Key-Value Observing. C'est pour ça que c'est conçu et c'est intentionnellement léger. (Parmi d'autres utilisations, c'est la base sur laquelle les liaisons Cocoa sont construites.) Si vous vous souciez d'un changement d'état qui n'est pas représenté par une propriété, alors les notifications sont plus appropriées. Par exemple, pour rester synchronisé lorsque l'utilisateur change le nom d'un objet modèle, j'utiliserais KVO. Pour savoir quand un graphique d'objet entier a été enregistré, j'utiliserais des notifications.

+4

Bonne réponse - mais avec l'approche KVO, comment supprimer un observateur qui s'est enregistré avec de nombreux objets? J'ai pensé (à tort) que le KVO utilisait les notifications sous le capot - mais je ne le pense pas. Ainsi, après avoir utilisé addObserver: X forKeyPath: ..., si vous essayez de faire plus tard: [[NSNotificationCenter defaultCenter] removeObserver: X] cela ne fonctionne pas? Cela semble impliquer que vous devez garder une liste séparée de tous les objets que X observe afin que vous puissiez supprimer l'observation. Ou ai-je oublié quelque chose? – TimM

+0

@TimM: Vous appelez la méthode appropriée pour l'objet observé. Par exemple: '[self removeObserver: theObserver forKeyPath: @" someProperty "];' – FreeAsInBeer

+0

Nouveau dans OS X 10.7 Lion et iOS 5.0, il existe une méthode -removeObserver: forKeyPath: context: à laquelle vous pouvez passer le même contexte que vous avez passé ajouter l'observateur. Vous devriez le faire autant que possible, dans le cas où plusieurs objets observent le même chemin clé. –

0

Ce n'est généralement pas le cas. Jetez un oeil à la discussion here, en particulier le lien vers la documentation Apple.

Si vous voulez toujours le faire comme vous le dites, il n'est pas particulièrement difficile d'implémenter quelque chose comme des reliures «à la main». Vous devez simplement créer un objet "binding" qui sait comment s'abonner aux modifications et se connecte à une propriété d'une vue. Pour réellement répondre à la façon dont c'est fait - normalement, vous avez un objet contrôleur qui surveille l'état du modèle (agissant quelque chose comme un observateur), et met à jour le ou les objets de vue si nécessaire.

+0

Je demande simplement quel est le meilleur moyen et donne un exemple JAVA. Je ne suis pas particulièrement ému si le mode Objective-C est totalement différent, je veux juste savoir ce que c'est. – rustyshelf

+0

J'ai compris. J'ai édité ma réponse pour clarifier ce dont je parlais. –

9

J'ai aussi trouvé que vous pouvez faire:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleWhateverChange) name:@"whateverChange" object:nil]; 

Pour vous inscrire à des événements de changement, et

[[NSNotificationCenter defaultCenter] postNotificationName:@"whateverChange" object:nil]; 

y mettre le feu.Je pourrais être un N00b mais je ne pouvais pas obtenir l'observateur de la chose de chemin clé pour travailler pour moi.

Questions connexes