2009-07-17 8 views
50

Digamos que tengo una clave @ "MyPreference", con un valor correspondiente almacenado a través de NSUserDefaults.Cocoa - ¿Cambia la notificación en NSUserDefaults?

¿Hay alguna manera de ser notificado cuando se modifica el valor?

¿O podría hacerse a través de fijaciones? (Pero en este caso, en lugar de vincular el valor a un elemento UI, deseo que mi objeto sea notificado del cambio para que pueda realizar otras tareas).

Soy consciente de que NSUserDefaultsDidChangeNotification se puede observar, pero esto parece ser un enfoque de todo o nada, y no parece haber un mecanismo para llegar al par clave-valor específico que se modificó. (. No dude en corregir)

Respuesta

77

pasado todo el día en busca de la respuesta, sólo para descubrir que 10 minutos después de hacer la pregunta ...

se encontró con una solución a través de valores-clave-Observación:

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

O, más simplemente (por comentario más abajo):

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

También puede llamar a este método de '[NSUserDefaults standardUserDefaults]' y no tener que anteponer los "valores". a la ruta clave. Los otros parámetros permanecen sin cambios. –

+6

No pude hacer que funcione porque Quin sugirió usar '[NSUserDefaults standardUserDefaults]'. Sin embargo, el apéndice de cadena no es necesario como '... forKeyPath: @" values.MyPreference "...' funcionará. Además, deberá implementar '- (void) observeValueForKeyPath: (NSString *) keyPath ofObject: (id) objeto change: (NSDictionary *) cambie contexto: (void *) context;' para capturar realmente el evento. – TrevorL

+0

Hola TrevorL ... aunque stringByAppendingString: no es necesario, ayuda al crear un método genérico - (void) observePreferencia: (NSString *) pref {... [@ "values." stringByAppendingString: pref] ... – Arvin

9

y empleado de Apple recomienda utilizar la notificación NSUserDefaultsDidChangeNotification aquí: https://devforums.apple.com/message/237718#237718

+6

La desventaja de esto es que no puede saber QUÉ configuración se modificó. – Emmanuel

+2

Sí, pensaría que habrían puesto al menos las claves modificadas en el diccionario userInfo de NSUserDefaultsDidChangeNotification, pero no: "Esta notificación no contiene un diccionario userInfo."Peor aún, la única especificación de cuándo se publica NSUserDefaultsDidChangeNotification dice que se publica" cuando se cambia un dominio persistente ". Probablemente me llevaría 20 minutos de investigación para confirmar exactamente lo que eso significa, y entonces no estoy seguro de que lo confiaría. –

13

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") 
} 
+0

no se olvide de eliminar el observador ya que está explicando el enfoque completo – slxl

0

estoy de acuerdo con @DenNukem. Estaba usando NSKeyValueObservingOptionNew. Pero esta función comenzó a darme el código BADACCESS = 1 error dondequiera que usé el NSUserdefault para guardar otros objetos. En caso de que esté utilizando Key Value Observer, solo tenga en cuenta el problema Zombie en NSUserDefaults.

Aquí está el enlace a la solución: NSUserDefaults and KVO issues

Cuestiones relacionadas