I have the models which is Group
and Thread
which have relation like
Group 1-Many Thread
I have this code, which will be trigger when leave group happens
[RLMRealm transactionWithBlock:^(RLMRealm *realm) {
// Clear all unread in threads
RLMResults<Thread *> *threads = [Thread allThreadsInGroupID:self._id];
for (Thread *thread in threads) {
[thread clearLocalUnreads]; // <-- Trigger KVO for thread
}
// Delete group
[realm deleteObject:self];
} error:nil];
In the ViewController
, I use KVO
to observe some property of Thread
and call this method when something changed
- (void)threadsControllerDidReloadData:(ThreadsController *)controller {
// To prevent realm notification infinite loop in WorkspaceKPIDatasource
if ([self.tableView.dataSource isKindOfClass:[WorkspaceTableViewController class]]) {
WorkspaceTableViewController *workspaceTVC = (WorkspaceTableViewController *)self.tableView.dataSource;
if ([workspaceTVC.contentDatasource isKindOfClass:[WorkspaceThreadsDatasource class]]) {
[self.tableView reloadData];
// Fix crash when reloadData is try to access group during leave since calling reloadData, the update
// will not happen immediately. This line will force the layout to update immediately result in calling
// - cellForRowAtIndexPath in the same run loop to prevent accessing invalidate group
[self.tableView.superview layoutIfNeeded]; // <-- This solve crash
}
[workspaceTVC refreshHeader];
}
}
There are two problems here
- KVO is trigger without realm transaction complete
cellForRowAtIndexPath
after callingreloadData
will not run immediately result in even though theKVO
trigger before group removed, when the cells are layout it crash why trying to access invalidate group.
I overcome this problem by choosing option 2 for now since it is easiest.
But I think the more reasonable way to do is let KVO
trigger only after transaction is completed. In that case no matter what happen in the transaction will be grouped at the end.
Because of this problem which lead me to think that KVO
for realm maybe will likely to cause some problem like if transaction is failed midway but somehow KVO
is already trigger because of the change at object level.
But by reading the document here. It seems to me like the KVO
will call when write transaction occur but I don't know why in my case when Thread
is updated and - threadsControllerDidReloadData:
is called why [group isInvalidated]
still return NO
in that method
From the sound of it, KVO might not be appropriate for what you're trying to accomplish.
If you're interacting with data in a table view, it might be more appropriate to use Realm's fine-grained notifications to register for changes. That system is designed to work with table views and will defer and deliver notifications at a time more appropriate for updating table view content.