Search code examples
objective-cparse-platformreactive-cocoa

ReactiveCocoa chaining network operations failed


I tried to use ReactiveCocoa to do network operation chaining, but I failed. I can't figure out what is wrong with my code.

- (RACSignal *)pg_findObjectsInBackground {
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        [self findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
            if (error) {
                [subscriber sendError:error];
                return;
            }
            [subscriber sendNext:objects];
            [subscriber sendCompleted];
        }];

        return [RACDisposable disposableWithBlock:^{
            [self cancel];
        }];
    }];
}

- (RACSignal *)pg_countObjectsInBackground {
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {

        [self countObjectsInBackgroundWithBlock:^(int number, NSError *error) {
            if (error) {
                [subscriber sendError:error];
                return;
            }
            [subscriber sendNext:@(number)];
            [subscriber sendCompleted];
        }];

        return [RACDisposable disposableWithBlock:^{
            [self cancel];
        }];
    }];
}

    __block NSError *_error;
    @weakify(self)
    [[[self.query pg_countObjectsInBackground]flattenMap:^RACStream *(NSNumber *count) {
        @strongify(self)
        self.totalCount = [count integerValue];
        // Second, fetch experiences
        self.query.limit = self.pageSize;
        self.query.skip = self.pageSize * self.currentPage;
        return [self.query pg_findObjectsInBackground];
    }]subscribeNext:^(NSArray *experiences) {
        @strongify(self)
        [self.experiences removeAllObjects];
        [self.experiences addObjectsFromArray:experiences];
    } error:^(NSError *error) {
        _error = error;
    } completed:^{
        @strongify(self)
        if (finishBlock) {
            finishBlock(self, _error);
        }
    }];

The first request was successful. But as soon as I return [self.query pg_findObjectsInBackground], it went to disposableWithBlock directly.


Solution

  • Because you're using the same PFQuery object for both the count and the find object operation, the query gets canceled when you return from the flattenMap method. The flattenMap subscribes to the new signal (which is the same signal), which I believe causes the disposable to fire. A simple solution is to construct a new PFQuery and return it in the flattenMap block.

    I assumed you're using Parse, and if you are, you should tag it.