NSUserDefaults setObject 在线程中崩溃

NSUserDefaults setObject crashing in Thread

我正在后台做一些事情。我也尝试将对象写入标准用户默认值。 由于 iOS 9 它正在崩溃。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// calling some methods in the background
// also save a value to the user defaults
NSDate *aDate = [NSDate date];
[[NSUserDefaults standardUserDefaults] setObject:aDate forKey:@"date"]; // <-- crash: EXC_BAD_ACCESS

});

我找不到问题。 aDate 不为零。我也尝试在主线程(从后台线程)上执行 setObject:,但结果相同。

崩溃是零星的! 我做错了什么?

这是堆栈跟踪:

Crashed: com.apple.root.background-qos EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000000000010

Thread : Crashed: com.apple.root.background-qos 0 libobjc.A.dylib
0x0000000199b0dbd0 objc_msgSend + 16 1 Foundation
0x0000000185ea1eb4 -[NSObject(NSKeyValueObserverNotification) willChangeValueForKey:] + 324 2 CoreFoundation
0x0000000185090994 _CFPreferencesSetValueWithContainer + 168 3 Foundation 0x0000000185eb9138 -[NSUserDefaults(NSUserDefaults) setObject:forKey:] + 56 4 AIR 0x00000001000f201c -[ServerSyncAgent syncUnsyncedEntities] (ServerSyncAgent.m:212) 5 libdispatch.dylib
0x000000019a2e97b0 _dispatch_call_block_and_release + 24 6 libdispatch.dylib 0x000000019a2e9770 _dispatch_client_callout + 16 7 libdispatch.dylib 0x000000019a2f7bb0 _dispatch_root_queue_drain + 2140 8 libdispatch.dylib 0x000000019a2f734c _dispatch_worker_thread3 + 112 9 libsystem_pthread.dylib 0x000000019a4fd478 _pthread_wqthread + 1092

来自Apple's documentation

The NSUserDefaults class is thread-safe.

贴出的代码没问题。你的错误在别处。

编辑: 堆栈指出了错误的来源:

您在代码中的其他地方(或某些第 3 方库)正在向 [NSUserDefaults standardUserDefaults] 添加 KVO 观察器。然而,NSUserDefaults 不符合 KVO,因此您不能添加观察者。

如果需要对用户默认设置的更改做出反应,您必须使用 NSNotificationCenter 并注册 NSUserDefaultsDidChangeNotification

第二次编辑: 不确定何时更改,但在现代 iOS 和 macOS NSUserDefaults 中可以观察到键值对。与上面链接相同的文档现在清楚地指出:

You can use key-value observing to register observers for specific keys of interest in order to be notified of all updates to a local defaults database. For more details, see Key-Value Observing Programming Guide.