I hit an issue working with this notification. If I handle the notification on the mainQueue I get periodic lockups on startup, if I handle it on the notification thread I get errors about working with the database on the main thread.
__weak DatabaseManager *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:kCBLDatabaseChangeNotification
object:nil
queue:nil //or [NSOperationQueue mainQueue]
usingBlock:^(NSNotification * _Nonnull note) {
NSArray<CBLDatabaseChange *> *changes = note.userInfo[@"changes"];
[weakSelf databaseDidChange:changes];
}];
The warning when queue is nil:
14:27:20.050‖ WARNING: Exception caught in -[CBLDatabase doAsync:]:
***** THREAD-SAFETY VIOLATION: This database is being used on a thread it wasn't created on! Please see the concurrency guidelines in the Couchbase Lite documentation. *****
When using the mainQueue. Here are the two relevant threads that get deadlocked…
main thread:
frame #4: 0x000000018224cc50 CoreFoundationCFRunLoopRunSpecific + 384 frame #5: 0x0000000182c5ccfc Foundation
-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 308
frame #6: 0x00000001009c1e94 ConceptsMYWaitFor + 264 frame #7: 0x000000010099d34c Concepts
-[CBLDatabase waitFor:] + 64
frame #8: 0x00000001009a1464 Concepts`-[CBLLiveQuery waitForRows] + 144
other thread:
frame #0: 0x0000000181f07f24 libsystem_kernel.dylib__psynch_cvwait + 8 frame #1: 0x0000000181fd2ce8 libsystem_pthread.dylib
_pthread_cond_wait + 648
frame #2: 0x0000000182d268ec Foundation-[__NSOperationInternal _waitUntilFinished:] + 132 frame #3: 0x0000000182c5947c Foundation
-[__NSObserver _doit:] + 232
frame #4: 0x0000000182310dfc CoreFoundation__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20 frame #5: 0x000000018231061c CoreFoundation
_CFXRegistrationPost + 396
frame #6: 0x000000018231039c CoreFoundation___CFXNotificationPost_block_invoke + 60 frame #7: 0x0000000182379414 CoreFoundation
-[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1532
frame #8: 0x000000018224e6c8 CoreFoundation_CFXNotificationPost + 368 frame #9: 0x00000001009d1a94 Concepts
__42-[CBLDatabase(Internal) postNotification:]_block_invoke + 64
frame #10: 0x000000010099cfac Concepts`catchInBlock + 28
The end solution was to dispatch_async in the notification handler. e.g.
_weak DatabaseManager *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:kCBLDatabaseChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
dispatch_async(dispatch_get_main_queue(), ^ {
NSArray<CBLDatabaseChange *> *changes = note.userInfo[@"changes"];
[weakSelf databaseDidChange:changes];
});
}];
Can you see any potential problems with doing this?
One thing that would be useful would be to report the database in the notification. I have to get this via a document lookup at the moment. (we have two CB databases in our app).
Also, as you say it would be really useful to track the source on the revision. Should I open an issue on github for that?