停止在循环内重新加载UITableView

时间:2015-01-29 20:30:11

标签: ios objective-c

我有以下代码,我在循环中调用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);

    }];
}

3 个答案:

答案 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,则触发重新加载。

当然你不应该命名两个数组结果,如果内部数据会隐藏外部,特别是如果你打算调用其他人的代码«不是一个非常好的解决方案。»