0

我正在使用 RestKit .20 来映射两个对象。第二个对象依赖于第一个对象。所以第一个操作必须在第二个操作之前进行。操作完成后,控制器使用模型对象在表格视图中显示适当的信息。

第一个对象有一个唯一的 id,用于构成 url 请求的一部分,以获取附加到它的对象。它一切正常,请求正在获取信息并正确执行映射,但是操作的顺序都是错误的,我无法理解它!

这就是我想要发生的事情:

  1. View 加载并开始加载/映射第一个对象。
  2. 一旦第一个对象被加载,第二个对象就会被加载/映射。
  3. 表视图重新加载。

以下是会发生什么:

  1. 视图加载,加载表视图。
  2. 操作最后执行,每次执行块操作时都会重新加载数据 - 不是我想要的解决方案,但它是我让它工作的唯一方法。

我很难解释,所以这里有一些代码:(我省略了一些不相关的代码)

- (void)viewDidLoad
{
    [super viewDidLoad]; 
    [self loadFirstObjects];        
    //omitted code

}



- (void)loadFirstObjects {
    //omitted code

    [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
        self.pubRepos = mappingResult.array;
        [self loadSecondaryObjects];
    } failure:^(RKObjectRequestOperation *operation, NSError *error) {
        NSLog(@"ERROR: %@", error);
    }];

    [operation start];
}

- (void)loadSecondObjects
{
    for (FirstObject *firstObject in firstObjects) {

        //Omitted code

        [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
            SecondObject *secondObject = [mappingResult.array objectAtIndex:0];

            [secondObjects setObject:secondObject forKey:secondObject.idNum];
            [table reloadData];
        } failure:^(RKObjectRequestOperation *operation, NSError *error) {
            NSLog(@"ERROR: %@", error);
        }];

        [operation start];

    }
}

那么我如何让这个以我想要的方式工作呢?我希望能够先执行请求/映射,然后将所有信息加载到表中并更新它。我需要不断地从 Web 服务重新加载/映射新数据,以便与重新加载表分开。

所以换句话说,这里最大的问题是:我如何准确控制操作块何时执行?

4

1 回答 1

1

一种相当容易做到这一点的方法是使用dispatch_group. 您的-loadSecondObjects方法可能如下所示:

- (void)loadSecondObjects
{
    dispatch_group_t group = dispatch_group_create();

    for (FirstObject *firstObject in firstObjects) {
        // Omitted code
        dispatch_group_enter(group);
        [operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
            SecondObject *secondObject = [mappingResult.array objectAtIndex:0];
            [secondObjects setObject:secondObject forKey:secondObject.idNum];
            dispatch_group_leave(group);
        } failure:^(RKObjectRequestOperation *operation, NSError *error) {
            NSLog(@"ERROR: %@", error);
            dispatch_group_leave(group);
        }];

        [operation start];
    }

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        [table reloadData];
    });
}

本质上,这里发生的事情是您将dispatch_group用作方便的计数器,并具有附加功能,您可以设置一个块以在计数器下一次达到零时执行。计数器从 0 开始。对于您开始的每个第二个对象加载,您递增计数器(通过调用dispatch_group_enter),然后对于每个完成(或失败)的第二个对象加载,您减少计数器(通过调用dispatch_group_leave)。当计数器达到 0 时,您设置的块dispatch_group_notify将被执行(并且您可以在那时知道您所有的第二个对象加载操作都已完成。)

PS:由于我在您的代码中没有看到任何保留/释放调用,我假设您使用的是 ARC。如果你不是,那么你将需要dispatch_release组。

于 2013-09-05T11:53:09.913 回答