2012-06-03 20 views
8

Este código llamará al método "defaultsChanged", cuando algún valor en UserDefaults cambióNSUserDefaultsDidChangeNotification: ¿Cuál es el nombre de la clave, que cambió?

NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 
[center addObserver:self 
      selector:@selector(defaultsChanged:) 
       name:NSUserDefaultsDidChangeNotification 
      object:nil]; 

Este Código me dará el valor que cambió

- (void)defaultsChanged:(NSNotification *)notification { 
    // Get the user defaults 
    NSUserDefaults *defaults = (NSUserDefaults *)[notification object]; 

    // Do something with it 
    NSLog(@"%@", [defaults objectForKey:@"nameOfThingIAmInterestedIn"]); 
} 

pero ¿cómo puedo obtener el nombre de la clave, eso cambio ??

Respuesta

28

Como han indicado otros, no hay forma de obtener la información sobre la clave modificada de NSUserDefaultsDidChange Notification. Pero no hay necesidad de duplicar cualquier contenido y comprobar por sí mismo, porque no hay Clave Valor Observación (MVA) que también trabaja con el NSUserDefaults, si es necesario específicamente ser notificado de un cierta propiedad:

en primer lugar, se registra para MVA en lugar de utilizar el NotificationCenter:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
[defaults addObserver:self 
      forKeyPath:@"nameOfThingIAmInterestedIn" 
       options:NSKeyValueObservingOptionNew 
       context:NULL]; 

no olvide quitar la observación (por ejemplo, en viewDidUnload o dealloc)

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
[defaults removeObserver:self forKeyPath:@"nameOfThingIAmInterestedIn"]; 

y finalmente poner en práctica este método para recibir notificaciones MVA

-(void)observeValueForKeyPath:(NSString *)keyPath 
       ofObject:(id)object 
        change:(NSDictionary *)change 
        context:(void *)context 
{ 
    NSLog(@"KVO: %@ changed property %@ to value %@", object, keyPath, change); 
} 
+0

Esto parece aplicarse solo cuando los valores predeterminados se cambian desde el interior de la aplicación, no desde el paquete de configuraciones. – Koraktor

+0

@Koraktor: en este caso específico, puede agregar el habitual NSUserDefaultsDidChangeNotification – auco

+0

@auco las cosas cambian constantemente: en iOS 6 viewDidUnload está en desuso. Uno debería usar (nulo) didReceiveMemoryWarning en su lugar. Y gracias por su publicación ;-) – coco

2

No hay datos provistos en el diccionario de notificación userInfo, por lo que parece que no tiene suerte a menos que desee guardar otra copia de los datos almacenados en NSUserDefaults en otro lugar y realizar una diferencia en los dos diccionarios.

+0

¿Hay otra manera, para obtener el nombre de la clave cambiada? – smudo78

+0

Como dije, puede mantener un clon de los datos almacenados en 'NSUserDefaults' en otro lugar y comparar los dos diccionarios para ver qué cambió. –

1

notificaciones Uso personalizados para determinar qué es exactamente lo que sucedió, por ejemplo .:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:self.event, @"eventObject", nil]; 
[[NSNotificationCenter defaultCenter] postNotificationName:@"newEventCreated" object:nil userInfo:options]; 

Si no es una opción con userDefaults, a continuación, que acaba de leer todos los valores predeterminados del usuario cada vez que reciba su notificación NSUserDefaultsDidChangeNotification y compair con los anteriores.

1

sólo tiene que añadir [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];

a su método de appDidBecomeActive y luego añadir

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(settingsChangedListener) name:NSUserDefaultsDidChangeNotification object:nil];

a su applicationDidEnterBackground

luego use el observador KVO como se muestra arriba cuando esté en primer plano

-1

Puede usar dictionaryRepresentation para obtener la copia completa de NSUserDefaults como NSDictionary. Entonces se trata de comparar valores previos y nuevos.

NSUserDefaults no es compatible con KVO, el hecho de que pueda desencadenar algunas notificaciones de KVO no se debe confiar y está sujeto a cambios aparentemente.

Por ejemplo:

- (void)setupUserDefaults { 
    self.userDefaults = [NSUserDefaults standardUserDefaults]; 
    [self.userDefaults registerDefaults:@{ /* ... */ }]; 

    self.userDefaultsDictionaryRepresentation = [self.userDefaults dictionaryRepresentation]; 

    [notificationCenter addObserver:self 
          selector:@selector(userDefaultsDidChange:) 
           name:NSUserDefaultsDidChangeNotification 
          object:self.userDefaults]; 
} 

- (void)userDefaultsDidChange:(NSNotification *)note { 
    NSDictionary *oldValues = self.userDefaultsDictionaryRepresentation; 
    NSDictionary *newValues = [self.userDefaults dictionaryRepresentation]; 

    NSArray *allKeys = @[ /* list keys that you use */ ]; 

    for(NSString *key in allKeys) { 
     id oldValue = oldValues[key]; 
     id newValue = newValues[key]; 

     if(![oldValue isEqual:newValue]) { 
      [self notifyObserversForKeyChange:key oldValue:oldValue newValue:newValue]; 
     } 
    } 

    self.userDefaultsDictionaryRepresentation = newValues; 
} 
Cuestiones relacionadas