我正在使用 RestKit .20 映射两个对象。第二个对象依赖于第一个。因此第一个操作必须在第二个操作之前进行。操作完成后, Controller 使用模型对象在表格 View 中显示适当的信息。
第一个对象有一个唯一的 id,用于构成 url 请求的一部分,以获取附加到它的对象。它的所有工作和请求正在获取信息并正确执行映射,但是操作顺序都是错误的,我只是无法理解它!
这就是我想要发生的事情:
- View 加载并开始加载/映射第一个对象。
- 加载第一个对象后,将加载/映射第二个对象。
- 表格 View 重新加载。
这是发生了什么:
- 查看加载,加载 TableView 。
- 操作最后执行,每次执行 block 操作时都会重新加载数据 - 这不是我想要的解决方案,但这是我可以让它工作的唯一方法。
我很难解释,所以这里有一些代码:(我省略了一些不相关的代码)
- (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 服务重新加载/映射新数据,以便与重新加载表分开。
换句话说,这里最大的问题是:如何准确控制操作 block 的执行时间?
最佳答案
一种相当简单的方法是使用 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
作为一个方便的计数器,并具有附加功能,您可以设置一个 block ,以便在计数器下次达到零时执行。计数器从 0 开始。对于开始的每个第二个对象加载,您递增计数器(通过调用 dispatch_group_enter
),然后对于完成(或失败)的每个第二个对象加载,您递减计数器(通过调用 dispatch_group_leave
)。当计数器达到 0 时,您用 dispatch_group_notify
设置的 block 将被执行(此时您可以知道所有第二个对象加载操作都已完成。)
PS:由于我在您的代码中没有看到任何保留/释放类调用,因此我假设您正在使用 ARC。如果不是,那么您需要 dispatch_release
该组。
关于iOS:RestKit 操作阻止在我想要的时候执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18631514/