我有以下代码,我在循环中调用self.tableView reloadData
这是一个坏主意。如果我把它放在循环之外,那么它将不会按预期工作,因为它会在更新noOfGroceryItems
字段之前被调用。
我该如何改进?
-(void) populateShoppingLists {
[_groceriesService getAllShoppingLists:^(NSArray *results, NSError *error) {
if(error) {
NSLog(@"%@",error.localizedDescription);
}
for(CKRecord *record in results) {
ShoppingList *shoppingList = [[ShoppingList alloc] initWithRecord:record];
// get the number of grocery items in the shopping list
[_groceriesService getItemsByShoppingList:shoppingList result:^(NSArray *results, NSError *error) {
shoppingList.noOfGroceryItems = results.count;
[_shoppingLists addObject:shoppingList];
// THIS IS BAD IDEA
**dispatch_async(dispatch_get_main_queue(), ^{
_shoppingLists = [_shoppingLists sort:@"title" ascending:YES];
[self.tableView reloadData];
});**
}];
}
}];
}
getItemsShoppingList方法的实现:
-(void) getItemsByShoppingList:(ShoppingList *)shoppingList result:(GetItemsByShoppingList) getItemsByShoppingList
{
CKQuery *query = [[CKQuery alloc] initWithRecordType:@"GroceryItems" predicate:[NSPredicate predicateWithFormat:@"ShoppingList == %@",shoppingList.record]];
[_privateDB performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
getItemsByShoppingList(results,error);
}];
}
答案 0 :(得分:0)
如果你在for循环后放置dispatch_async
,那么你就可以保证在循环完成后将在主队列上调度该块(并且你的数据是更新)。
为什么不在处理和更新所有模型后立即发送reloadData
电话 ?
答案 1 :(得分:0)
当且仅当最后一个购物清单被提取时,您可以添加条件以重新加载表格,例如:
[_groceriesService getAllShoppingLists:^(NSArray *results, NSError *error) {
if(error) {
NSLog(@"%@",error.localizedDescription);
}
// Variable to count the number
// of records processed
__block int recordsProcessed = 0;
for(CKRecord *record in results) {
ShoppingList *shoppingList = [[ShoppingList alloc] initWithRecord:record];
// (I've changed this second results variable from results
// to results2 in order to distinguish between the two
// "results" variables.)
// get the number of grocery items in the shopping list
[_groceriesService getItemsByShoppingList:shoppingList
result:^(NSArray *results2, NSError *error) {
shoppingList.noOfGroceryItems = results2.count;
[_shoppingLists addObject:shoppingList];
dispatch_async(dispatch_get_main_queue(), ^{
_shoppingLists = [_shoppingLists sort:@"title" ascending:YES];
// Increment recordsProcessed to indicate another
// record has been processed
recordsProcessed ++;
// If all the records have been processed,
// reload the table (using the outer block's
// results variable, not the inner block's result2
// variable).
if (recordsProcessed == results.count) {
[self.tableView reloadData];
}
});
}];
}
}];
更新以及第二种解决方案。假设_shoppingLists
空出来,您可以简单地将results
与放入_shoppingLists
的元素数进行比较,例如:
[_groceriesService getAllShoppingLists:^(NSArray *results, NSError *error) {
if(error) {
NSLog(@"%@",error.localizedDescription);
}
for(CKRecord *record in results) {
ShoppingList *shoppingList = [[ShoppingList alloc] initWithRecord:record];
// (I've changed this second results variable from results
// to results2 in order to distinguish between the two
// "results" variables.)
// get the number of grocery items in the shopping list
[_groceriesService getItemsByShoppingList:shoppingList
result:^(NSArray *results2, NSError *error) {
shoppingList.noOfGroceryItems = results2.count;
[_shoppingLists addObject:shoppingList];
dispatch_async(dispatch_get_main_queue(), ^{
_shoppingLists = [_shoppingLists sort:@"title" ascending:YES];
// If the number of shopping lists stored
// equals the number of records processed,
// reload the table (using the outer block's
// results variable, not the inner block's result2
// variable).
if (_shoppingLists.count == results.count) {
[self.tableView reloadData];
}
});
}];
}
}];
答案 2 :(得分:0)
您可以使用块枚举,而不是快速枚举结果数组,而是为您提供当前对象的索引。如果索引为[results count] - 1
,则触发重新加载。
当然你不应该命名两个数组结果,如果内部数据会隐藏外部,特别是如果你打算调用其他人的代码«不是一个非常好的解决方案。»