【问题标题】:NSUserDefaultsDidChangeNotification: What's the name Of the Key, that Changed?NSUserDefaultsDidChangeNotification:密钥的名称是什么,已更改?
【发布时间】:2015-11-30 18:20:46
【问题描述】:

当 UserDefaults 中的某些值发生更改时,此代码将调用方法“defaultsChanged”

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

这个代码会给我改变的价值

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

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

但是我怎样才能得到密钥的名称,改变了??

【问题讨论】:

    标签: objective-c ios xcode nsuserdefaults nsnotificationcenter


    【解决方案1】:

    正如其他人所说,没有办法从 NSUserDefaultsDidChange 通知中获取有关更改密钥的信息。但是没有必要复制任何内容并自己检查,因为有 Key Value Observing (KVO) 也适用于 NSUserDefaults,如果您需要特别通知某个属性

    首先,注册 KVO,而不是使用 NotificationCenter:

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

    不要忘记删除观察结果(例如在 viewDidUnload 或 dealloc 中)

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

    最后实现这个方法来接收KVO通知

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

    【讨论】:

    • 这似乎只适用于从应用程序内部更改默认值而不是从设置包中更改的情况。
    • @Koraktor:在这种特定情况下,您仍然可以添加通常的 NSUserDefaultsDidChangeNotification
    • @auco 事情在不断变化:在 iOS 6 中 viewDidUnload 已被弃用。应该使用 (void)didReceiveMemoryWarning 代替。并感谢您的帖子;-)
    • @coco:感谢您的提示。这就是我写“例如在 viewDidUnload 或 dealloc 中”的原因。 -didReceiveMemoryWarning 不是最佳选择,因为当没有低内存警告时,它可能永远不会被调用。对于iOS6,最好的地方是dealloc。
    • 我在 Mac 上使用它,所以它也应该在那里工作。
    【解决方案2】:

    通知的userInfo 字典中没有提供任何数据,所以看起来你很不走运,除非你想在其他地方保留存储在NSUserDefaults 中的数据的另一个副本并在两个字典上执行差异.

    【讨论】:

    • 还有其他方法,获取更改后密钥的名称吗?
    • 就像我说的,您可以将存储在NSUserDefaults 中的数据复制到其他地方,然后比较两个字典,看看有什么变化。
    【解决方案3】:

    使用自定义通知来确定到底发生了什么,例如:

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

    如果它不是 userDefaults 的选项,那么每次收到 NSUserDefaultsDidChangeNotification 通知时,只需读取所有用户默认值并将其与之前的比较。

    【讨论】:

      【解决方案4】:

      只需添加[[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil];

      到您的appDidBecomeActive 方法,然后添加

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

      致您的applicationDidEnterBackground

      然后在前台使用 KVO 观察者,如上所示

      【讨论】:

        【解决方案5】:

        您可以使用dictionaryRepresentation 来获取NSUserDefaults 的完整副本作为NSDictionary。然后就是比较以前的值和新的值了。

        NSUserDefaults 不符合 KVO,它可能会触发一些 KVO 通知这一事实不应被依赖,并且显然会发生变化。

        例如:

        - (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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-11-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-09-10
          • 1970-01-01
          相关资源
          最近更新 更多