53 votes

Cocoa - Notification en cas de changement de valeur de NSUserDefaults ?

Disons que j'ai une clé @"MyPreference" avec une valeur correspondante stockée dans NSUserDefaults .

Existe-t-il un moyen d'être averti lorsque la valeur est modifiée ?

Ou cela pourrait-il se faire par le biais de fixations ? (Dans ce cas, au lieu de lier la valeur à un élément de l'interface utilisateur, je souhaite que mon objet soit informé du changement, afin que je puisse effectuer d'autres tâches).

Je suis conscient que NSUserDefaultsDidChangeNotification peut être observée, mais il s'agit d'une approche "tout ou rien", et il ne semble pas y avoir de mécanisme permettant d'accéder à la paire clé-valeur spécifique qui a été modifiée. (N'hésitez pas à corriger).

81voto

SirRatty Points 696

J'ai passé toute la journée à chercher la réponse, pour la trouver 10 minutes après avoir posé la question...

J'ai trouvé une solution grâce à l'observation de la valeur des clés (Key-Value-Observing) :

[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self
    forKeyPath:@"values.MyPreference"
    options:NSKeyValueObservingOptionNew
    context:NULL];

Ou, plus simplement (selon le commentaire ci-dessous) :

[[NSUserDefaults standardUserDefaults] addObserver:self
                                        forKeyPath:@"MyPreference"
                                           options:NSKeyValueObservingOptionNew
                                           context:NULL];

14 votes

Vous pouvez également appeler cette méthode sur [NSUserDefaults standardUserDefaults] et ne pas avoir à ajouter le mot "values" au chemin d'accès à la clé. Les autres paramètres restent inchangés.

6 votes

Je n'ai pas réussi à le faire fonctionner comme Quin l'a suggéré en utilisant [NSUserDefaults standardUserDefaults] . Cependant, l'appendice de la chaîne n'est pas nécessaire car ...forKeyPath:@"values.MyPreference"... fonctionnera. Vous devrez également mettre en œuvre - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; pour capturer l'événement.

0 votes

Bonjour TrevorL... même si stringByAppendingString : n'est pas nécessaire, il est utile lors de la création d'une méthode générique - (void) observePreference :(NSString *)pref { ...[@"values." stringByAppendingString:pref] ...

23voto

Brian Points 3134

Swift :

override func viewDidLoad() {
  super.viewDidLoad()
  NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "THE KEY", options: NSKeyValueObservingOptions.New, context: nil)
}

override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
  // your logic
}

deinit {
  NSUserDefaults.standardUserDefaults().removeObserver(self, forKeyPath: "THE KEY")
}

11voto

DenNukem Points 3455

L'employé d'Apple a conseillé d'utiliser la notification NSUserDefaultsDidChangeNotification ici : https://devforums.apple.com/message/237718#237718

8 votes

L'inconvénient de cette méthode est que vous ne pouvez pas savoir lequel des paramètres a été modifié.

2 votes

Oui, on aurait pu penser qu'ils auraient au moins mis les clés modifiées dans le dictionnaire userInfo de NSUserDefaultsDidChangeNotification, mais non : "This notification does not contain a userInfo dictionary." (Cette notification ne contient pas de dictionnaire userInfo). Pire encore, la seule spécification du moment où NSUserDefaultsDidChangeNotification est affichée indique qu'elle est affichée "lorsqu'un domaine persistant est modifié". Il me faudrait probablement 20 minutes de recherche pour confirmer exactement ce que cela signifie, et je ne suis pas sûr de pouvoir m'y fier.

0 votes

Cette méthode présente un autre inconvénient : si un programme externe modifie les paramètres par défaut de votre application, par exemple en utilisant la commande cmd "defaults write" ou l'application Prefs Editor, vous n'en serez pas averti. En revanche, la technique KVO vous préviendra.

0voto

Tarika Chawla Points 108

Je suis d'accord avec @DenNukem. J'utilisais le NSKeyValueObservingOptionNew . Mais cette fonction a commencé à me donner le BAD_ACCESS Code=1 à chaque fois que j'ai utilisé l'option NSUserDefault afin de sauvegarder d'autres objets. Si vous utilisez l'observateur clé-valeur (KVC), soyez conscient du problème de Zombie sur le site NSUserDefaults .

Voici le lien vers la solution : NSUserDefaults et problèmes liés à l'OVK

Prograide.com

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.

Powered by:

X