简体   繁体   English

为什么我的 UITableView 在异步重新加载数据期间滚动时会失去流动性?

[英]Why does my UITableView lose it's fluidity when I scroll during an asynchronous reload data?

Here is my problem... I'm making an asynchronous call to the service I'm working with, which returns search results back to me.这是我的问题...我正在对我正在使用的服务进行异步调用,它将搜索结果返回给我。 When that's done, it reloads my table, and the async is done.完成后,它会重新加载我的表,并且异步完成。 The problem is, when I try scrolling on my table view before the async call is done, the table loses that fluid feeling that all scroll views have.问题是,当我在异步调用完成之前尝试滚动表格视图时,表格会失去所有滚动视图所具有的流畅感。 What I mean by this is that when you let go of the scroll, rather than keeping going and slowly stopping, it just halts as soon as you let go.我的意思是,当您让 go 滚动时,而不是继续前进并缓慢停止,只要您让 go 停止,它就会停止。 The only way to restore the fluid feeling is to scroll all the way to the top or bottom of the UITableView and a little past, then it's fine.恢复流畅感的唯一方法就是一直滚动到UITableView的顶部或底部再往前一点,就可以了。

Here is my code for the async call:这是我的异步调用代码:

__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;
    });

Also, keep in mind that I'm using a custom UITableViewCell.另外,请记住,我使用的是自定义 UITableViewCell。 If any other information is needed, please request it and I'll see what I can do.如果需要任何其他信息,请提出要求,我会看看我能做些什么。 Thank you in advance.先感谢您。

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

EDIT2: I'm testing on an iPod Touch running 4.3.1 (8G4) 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;
}

Solution:解决方案:

What I actually ended up doing was locking down the table and all UI elements until the call was done.我实际上最终做的是锁定表格和所有 UI 元素,直到调用完成。 Maybe not the best solution, but it worked none the less.也许不是最好的解决方案,但它仍然有效。

Calling [tableView reloadData] will reload your ENTIRE table, which is the reason you are seeing the choppy UITableView.调用[tableView reloadData]将重新加载您的整个表,这就是您看到不稳定的 UITableView 的原因。 It forces all visible cells to refresh, so as you are scrolling, the visible cells are refreshing and repainting themselves.它强制所有可见单元格刷新,因此当您滚动时,可见单元格正在刷新并重新绘制自己。 You'll need to reevaluate your strategy for updating the UITableView as you have data coming in to avoid this.您需要重新评估更新 UITableView 的策略,因为您有数据进入以避免这种情况。 You should update individual cells that could be visible that have data that pertain to your updates.您应该更新可能可见的具有与您的更新相关的数据的单个单元格。

To do this, you will need to use the following methods:为此,您将需要使用以下方法:

– insertRowsAtIndexPaths:withRowAnimation:

– deleteRowsAtIndexPaths:withRowAnimation:

– reloadRowsAtIndexPaths:withRowAnimation:

The combination of these will allow you to update your table (add/remove rows), as you receive data, and not force the refresh of the entire table.这些组合将允许您在接收数据时更新表(添加/删除行),而不是强制刷新整个表。

I would like to see the custom cell, to fully answer your problem.我想查看自定义单元格,以充分回答您的问题。

Also, the cellForRowAtIndexPath: segment of your table controller, to see how you are reusing your cells.此外,表格 controller 的 cellForRowAtIndexPath: 段,以查看您如何重用单元格。

Last, but not least: Which type of device are you testing on?最后但同样重要的是:您正在测试哪种类型的设备? (type and generation) (类型和世代)

EDIT:编辑:

This part:这部分:

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;
}

looks downright poisonous... Dont have the time to test it right now, but please never add cells within a cell... the tablecontroller will be not only confused, but block out too much memory.看起来完全有毒......现在没有时间测试它,但请不要在单元格中添加单元格......表格控制器不仅会混淆,而且会阻止太多memory。

Only use the cellForRowAtIndexPath: for simple things like filling in titles, descriptions and images.仅将 cellForRowAtIndexPath: 用于简单的事情,例如填写标题、描述和图像。

Do your reload logic on the tableview controller, but somewhere safer.在 tableview controller 上执行重新加载逻辑,但在更安全的地方。 The cellForRowAtIndexPath will be loaded every time a cell appears, even if it was just in sight.每次出现单元格时都会加载 cellForRowAtIndexPath,即使它刚刚出现。

make sure you are only reloading table data on main thread.确保您只在主线程上重新加载表数据。 preferably, i use nsinvocation rather than GCD:)最好,我使用 nsinvocation 而不是 GCD :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM