我有以下代码,旨在捕获特定键的NSUserDefaults值更改事件。
[[NSUserDefaults standardUserDefaults] addObserver:self
forKeyPath:SOME_NSSTRING_VARIABLE
options:NSKeyValueObservingOptionNew
context:NULL];
- (void)observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context
{NSLog (@"Changed for key %@", keyPath); }
但是从不调用observeValueForKeyPath。我甚至尝试用Observing value changes to an NSUserDefaults key中提到的字符串替换SOME_NSSTRING_VARIABLE,但它没有帮助。
更新: 我正在从tabview中更改NSUserDefaults。上面监视更改的代码位于同一tabviewcontroller的不同选项卡中。在我监视更改的选项卡(上面代码所在的选项卡)中,如果我添加:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// NSLog(@"viewillappear");
NSUserDefaults *FUDefaults = [NSUserDefaults standardUserDefaults];
NSLog(@"The username obtained is: %@", [FUDefaults objectForKey:SOME_NSSTRING_VARIABLE]);
}
正确获取更新的NSUserDefaults值,但从未调用observeValueForKeyPath。
答案 0 :(得分:23)
修改:viewDidUnload
现已弃用,请使用dealloc
代替removeObserver
这应该完美,我刚刚在这里测试过。
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSUserDefaults standardUserDefaults] addObserver:self
forKeyPath:@"SomeKey"
options:NSKeyValueObservingOptionNew
context:NULL];
// Testing...
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"test" forKey:@"SomeKey"];
[defaults synchronize];
}
- (void)viewDidUnload
{
[super viewDidUnload];
[[NSUserDefaults standardUserDefaults] removeObserver:self forKeyPath:@"SomeKey"];
}
- (void)observeValueForKeyPath:(NSString *) keyPath ofObject:(id) object change:(NSDictionary *) change context:(void *) context
{
if([keyPath isEqual:@"SomeKey"])
{
NSLog(@"SomeKey change: %@", change);
}
}
你可以测试的东西。
在viewDidUnload中放置一个断点并确保视图没有消失(因为你正在从另一个viewController更改SomeKey
)如果是这种情况,那么可能会移动你的寄存器/ de-根据VC的工作方式将代码注册到init / dealloc中。
使用@"SomeKey"
之类的显式KeyPath而不是像SOME_NSSTRING_VARIABLE
答案 1 :(得分:8)
Swift 3版本:
override func viewDidLoad() {
super.viewDidLoad()
UserDefaults.standard.addObserver(self, forKeyPath: "keyPath", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "keyPath" {
//Do something
}
}
deinit {
UserDefaults.standard.removeObserver(self, forKeyPath: "keyPath")
}
答案 2 :(得分:3)
Swift版本:
func setUserDefaultsListener(){
NSUserDefaults.standardUserDefaults().addObserver(self, forKeyPath: "keyPath", options: NSKeyValueObservingOptions.New, context: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
if keyPath == "keyPath" {
//Do something
}
}
deinit {
NSUserDefaults.standardUserDefaults().removeObserver(self, forKeyPath: "keyPath")
}
答案 3 :(得分:1)
Swift 5版本:
extension UserDefaults {
@objc dynamic var keyPath: Int {
return integer(forKey: "keyPath")
}
}
提示:确保var
与keyPath
完全相同
以及使用观察者的位置:
var observer: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
observer = UserDefaults.standard.observe(\.keyPath, options: [.initial, .new], changeHandler: { (defaults, change) in
//Do something
})
}
deinit {
observer?.invalidate()
}