当我在异步重载数据中滚动时,为什么我的UITableView失去了它的流动性?

时间:2011-06-01 14:42:44

标签: iphone ios asynchronous uitableview

这是我的问题......我正在对我正在使用的服务进行异步调用,这会将搜索结果返回给我。完成后,它会重新加载我的表,并完成异步。问题是,当我在异步调用完成之前尝试滚动我的表视图时,表失去了所有滚动视图所具有的流畅感。我的意思是,当你放开卷轴,而不是继续前进并慢慢停止时,它会在你松开后立即停止。恢复流畅感的唯一方法是一直滚动到UITableView的顶部或底部并稍微过去,然后就可以了。

以下是我的异步调用代码:

__block NSMutableArray *appendMoreObjects = [[NSMutableArray alloc] init];

    dispatch_async( dispatch_get_main_queue(), ^{

        self.activity.hidden = NO;

        appendMoreObjects = [service search:self.query from:((moreCount * 8)) until:((moreCount * 8) + 8)];

        if( appendMoreObjects == nil )
        {
            //alert view
        }
        else
        {
            [self.allSearchResults addObjectsFromArray:appendMoreObjects];

            [self updateSearchArray];

            self.moreCount += 1;
        }

        self.activity.hidden = YES;
    });

另外,请记住我正在使用自定义UITableViewCell。如果需要任何其他信息,请提出要求,我会看到我能做些什么。提前谢谢。

EDIT1:[self updateSearchArray]包含[tableView reloadData]

EDIT2:我正在测试运行4.3.1(8G4)的iPod Touch

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
customCell * cell = (customCell *)[tableView dequeueReusableCellWithIdentifier:@"cell"];

if( cell == nil )
{
    cell = [[[customCell alloc] initWithFrame:CGRectZero] autorelease];
}

if( indexPath.row == [self.searchResults count] && [self.searchResults count] > 0)
{

    UITableViewCell *moreCell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease];
    moreCell.textLabel.text = @"More";
    moreCell.textLabel.textAlignment = UITextAlignmentCenter;

    return moreCell;
}

if( indexPath.row < [self.searchResults count] )
{
    [cell formatAndInsertData:[self.searchResults objectAtIndex:indexPath.row]];
}

return cell;
}

解决方案:

我实际上最终做的是锁定表和所有UI元素,直到调用完成。也许不是最好的解决方案,但它仍然有效。

3 个答案:

答案 0 :(得分:2)

调用[tableView reloadData]将重新加载您的ENTIRE表,这就是您看到波动的UITableView的原因。它会强制所有可见的单元格刷新,因此当您滚动时,可见的单元格会刷新并重新绘制自己。您需要重新评估更新UITableView的策略,因为您有数据进入以避免这种情况。您应该更新可见的具有与您的更新相关的数据的单个单元格。

为此,您需要使用以下方法:

– insertRowsAtIndexPaths:withRowAnimation:

– deleteRowsAtIndexPaths:withRowAnimation:

– reloadRowsAtIndexPaths:withRowAnimation:

这些组合将允许您在接收数据时更新表(添加/删除行),而不强制刷新整个表。

答案 1 :(得分:0)

我希望看到自定义单元格,以完全回答您的问题。

另外,您的表控制器的cellForRowAtIndexPath:段,以查看您如何重用您的单元格。

最后但并非最不重要:您正在测试哪种类型的设备? (类型和代)

编辑:

这部分:

if( indexPath.row == [self.searchResults count] && [self.searchResults count] > 0)
{

    UITableViewCell *moreCell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease];
    moreCell.textLabel.text = @"More";
    moreCell.textLabel.textAlignment = UITextAlignmentCenter;

    return moreCell;
}

看起来非常有毒...没有时间来测试它,但请永远不要在单元格中添加单元格......表格控制器不仅会混淆,而且会阻挡太多内存。

仅使用cellForRowAtIndexPath:来填写标题,描述和图像等简单的内容。

在tableview控制器上执行重载逻辑,但在某个地方更安全。每次出现一个单元格时都会加载cellForRowAtIndexPath,即使它刚看到它。

答案 2 :(得分:0)

确保您只在主线程上重新加载表数据。最好,我使用nsinvocation而不是GCD:)