在成功块中加载下一页时RKPaginator出错

时间:2014-03-13 15:38:19

标签: restkit restkit-0.20

我尝试使用Restkit和RKPaginator加载api的所有页面(在加载第一页之前我不知道页数)。

10次尝试中有1次,我收到以下错误

'NSInternalInconsistencyException',原因:'当一个人正在进行加载时无法执行加载。'

当此问题没有出现时,该功能正在按预期工作

我使用以下代码:

- (void)loadAllPagesForEntity:(NSString*)entityName
                      success:(void (^)(RKPaginator *paginator, NSArray *objects, NSUInteger page))success
{
    URObjectManager *objectManager = [URObjectManager sharedManager];

    NSString *requestString = [NSString stringWithFormat:@"%@?page=:currentPage&size=:perPage",entityName];

    RKPaginator* myPaginator = (RKPaginator*)[objectManager paginatorWithPathPattern:requestString];
    myPaginator.perPage = 50; // this will request /posts?page=N&per_page=20

    [myPaginator setCompletionBlockWithSuccess:^(RKPaginator *paginator, NSArray *objects, NSUInteger page)
     {
          if ([paginator hasNextPage]) { [paginator loadNextPage]; }
         else if (success) { success(paginator, objects, page); }
     }
     failure:^(RKPaginator *paginator, NSError *error)
     {
         NSLog(@"Failure: %@", error);
     }];

    [myPaginator loadPage:0];
}

此代码在更多实体上调用:

[self loadAllPagesForEntity:@"entity1" success:nil];
[self loadAllPagesForEntity:@"entity2" success:nil];

...

[self loadAllPagesForEntity:@"entity n" success:nil];

我的程序崩溃并被RKPaginator.m中的以下断言之一阻止: l.158

NSAssert(self.isLoaded, @"Cannot determine hasNextPage: paginator is not loaded.");

l.177

NSAssert(! self.objectRequestOperation, @"Cannot perform a load while one is already in progress.");

在成功块中测试hasNextPage或执行loadNextPage是不正确的? 这样做的正确方法是什么?

我尝试过没有成功使用:

[paginator performSelector:@selector(loadNextPage) onThread:[NSThread currentThread] withObject:nil waitUntilDone:NO];

在延迟纠正问题后执行选择器但不是可接受的解决方案。

2 个答案:

答案 0 :(得分:0)

似乎是RKPaginator.m中的一个错误(Restkit 0.23)。我会在找到时间后立即在github上填写请求。

似乎成功回调和请求操作的完成不是在同一个线程中完成的。

因此,当调用成功时,并不总是设置isLoaded。

我将代码更改为在执行成功回调之前始终调用操作结束。 它为我做了诀窍。

评论l.198

// Add KVO to ensure notification of loaded state prior to execution of completion block
//[self.objectRequestOperation addObserver:self forKeyPath:@"isFinished" options:0 context:nil];

L.221

[self.objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    [self operationFinished];

    if (self.successBlock) {
        self.successBlock(self, [mappingResult array], self.currentPage);            
    }
}

添加功能

-(void)operationFinished
{
    RKObjectRequestOperation*oro = self.objectRequestOperation;
    self.objectRequestOperation = nil;

    self.loaded = (oro.mappingResult != nil);
    self.mappingResult = oro.mappingResult;
    self.error = oro.error;
}

答案 1 :(得分:0)

我在RestKit github页面上发布了测试解决方案。 我希望它很快会合并,但是如果你需要它,现在可以随意使用我的叉子。

https://github.com/RestKit/RestKit/pull/2156

:)