[iOS] Key-Value Observing

lundi 30 janvier 2017

Key-Value Observing est considéré comme l’api la plus mauvaise de Cocoa.
En objective C, il y a un certain nombre de moyens pour faire communiquer des événements dans votre application:

      NSNotification & NSNotificationCenter => fourni un certain nombre d’événement du système qui peuvent notifier et être notifier n’importe ou dans l’application. Le tout est de connaître leur nom.
      Par exemple: UIApplicationDidReceiveMemoryWarningNotification signale lorsque que la batterie est presque vide
      Key-Value Observing => permet de demander à des objets d’être observer et de signaler tout changement au travers d’une clé définit en particulier.
      Par exemple UIProgressView à un observer sur l’événement numberOfBytesRead et quand celui ci change, il met à jour la propriété progress pour afficher le pourcentage correcte.
      Delegates => est le pattern le plus populaire et permet de signaler des événements sur des méthodes bien fixé.
      Par exemple: la méthode scrollViewDidScroll est appelé directement quand le scroll offset change de l’objet UIScrollView
      Callbacks => sont des block que l’on passe en argument de méthodes et qui seront appelé après que l’événement c’est correctement passé.

KVO est un protocol qui défini un mécanisme commun qui observe et notifie le changement d’état entre deux objets
Il est donc possible d’utiliser cette technique si on souhaite appeler une méthode dans une autre vue controleur.
Mais il faut être sur qu’on soit passé dans la méthode de la première vue qui ajoute l’observeur!
Par exemple,si dans une tableview vous avez défini des actions dans la page detail des rows de la tableview, vous ne pouvez pas créer un observer dans cette page detail et espérer par exemple dans la tableview faire un postnotification vers cet observer car il ne fonctionnera que dans le cas ou on sera au moins passé une fois dans la page detail d’une row.
J’ai rencontrer ce cas ou des actions de types sociaux on été défini dans le détail d’un article au travers de bouton twitter, facebook… Ces actions étaient défini dans le controleur de la page detail. Mais on m’a demandé de rajouter ces actions dans un swipeCell de la page qui liste les articles. Pas possible d’utiliser le KVO car si on ne passe jamais dans le detail de l’article on a pas accès aux actions sociaux définis dans la page detail de l’article. Dans ce cas-ci j’ai utiliser une classe singleton de type service pour regrouper les actions et les appeler partout dans l’application.

Vous trouverez un exemple d’utilisation simple de kvo ici

Mais il est aussi intéressant d’utiliser KVO pour signaler les changements des propriétés d’un objet de la classe.
Par exemple de manière générique créer un observer pour chaque propriété d’une classe:

-(void)registerKVO:(NSObject *)response
{
    NSArray * names = getPropertyNamesOf([response class]);
    
    for (NSString  * propertyName in names)
    {
        [response addObserver:self forKeyPath:propertyName options:NSKeyValueObservingOptionNew context:nil];
    }
}

-(void)unregisterKVO:(NSObject *)response
{
    NSArray * names = getPropertyNamesOf([response class]);
    
    for (NSString  * propertyName in names)
    {
        @try {
            [response removeObserver:self forKeyPath:propertyName];
        } @catch(id anException) {}
    }
}

Et maintenant il ne reste plus que d’utiliser la méthode

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    self.upd_usr = [TCUserManager sharedInstance].currentUser.identifier;
    self.upd_date = [NSDate new];
    [self save];
}

Et dans ce cas-ci chaque fois qu’un objet de type réponse est modifié on sauve l’utilisateur et la date à laquelle il a été modifié. L’option NSKeyValueObservingOptionNew indique que le dictionnaire de modification doit fournir la nouvelle valeur d’attribut, le cas échéant.

Il ne faut pas non plus oublier de toujours bien retirer l’observer quand on en a plus besoin !

Concernant cet article je me suis inspiré de l’article de Matt thompson ici

Tags: IOS , KVO