Roobiq / RBQFetchedResultsController

Drop-in replacement for NSFetchedResultsController backed by Realm.
MIT License
477 stars 70 forks source link

When init with a empty realm, the `notificationCollection`'s `notificationBlock` might never got call #107

Closed chml closed 1 year ago

chml commented 8 years ago
- (id<RLMCollection>)fetchObjects
{
    RLMResults *fetchResults = [self.realm allObjects:self.entityName]; // When init with a empty realm, this results would be empty; 

    // If we have a predicate use it
    if (self.predicate) {
        fetchResults = [fetchResults objectsWithPredicate:self.predicate];
    }

    // If we have sort descriptors then use them
    if (self.sortDescriptors.count > 0) {
        fetchResults = [fetchResults sortedResultsUsingDescriptors:self.sortDescriptors];
    }

    return fetchResults;
}
- (void)registerChangeNotifications
{
    typeof(self) __weak weakSelf = self;

    // Setup run loop
    if (!self.notificationRunLoop) {
        dispatch_semaphore_t sem = dispatch_semaphore_create(0);
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, ^{
                weakSelf.notificationRunLoop = [NSRunLoop currentRunLoop];

                dispatch_semaphore_signal(sem);
            });

            CFRunLoopRun();
        });

        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    }

    CFRunLoopPerformBlock(self.notificationRunLoop.getCFRunLoop, kCFRunLoopDefaultMode, ^{
        if (weakSelf.notificationToken) {
            [weakSelf.notificationToken stop];
            weakSelf.notificationToken = nil;
            weakSelf.notificationCollection = nil;
        }

        weakSelf.notificationCollection = weakSelf.fetchRequest.fetchObjects;

        // Then this notification block will never got call, after the initial call(`change = nil`);
        weakSelf.notificationToken = [weakSelf.notificationCollection
                                      addNotificationBlock:^(id<RLMCollection>  _Nullable collection,
                                                             RLMCollectionChange * _Nullable change,
                                                             NSError * _Nullable error) {
                                          if (!error &&
                                              change) {
                                              // Create the change sets
                                              NSSet *addedSafeObjects = [weakSelf safeObjectsFromChanges:change.insertions withCollection:collection isInsertion:YES];
                                              NSSet *deletedSafeObjects = [weakSelf safeObjectsFromChanges:change.deletions withCollection:collection isInsertion:NO];
                                              NSSet *changedSafeObjects = [weakSelf safeObjectsFromChanges:change.modifications withCollection:collection isInsertion:NO];

                                              [weakSelf calculateChangesWithAddedSafeObjects:addedSafeObjects
                                                                          deletedSafeObjects:deletedSafeObjects
                                                                          changedSafeObjects:changedSafeObjects
                                                                                       realm:collection.realm];
                                          }
                                      }];
    });

    CFRunLoopWakeUp(self.notificationRunLoop.getCFRunLoop);
}