使用线程更新UITableView

时间:2010-07-30 20:05:26

标签: iphone cocoa-touch multithreading uitableview

我正在为iPhone创建一个词典应用程序,在用户输入时提供结果。我使用线程(NSThread)来更新UITableView,以便不阻塞主线程。

但是,当UITableView向数据源询问行数时会发生崩溃(tableView:numberOfRowsInSection :),然后我返回10,然后它会向数据源询问单元格0-9(tableView:cellForRowAtIndexPath: )。但是当它要求单元格7时,数据源已经改变了,现在它只有5行,从而导致崩溃。

以下是我解决问题的方法:

我在init方法中创建了一个NSLock。

以下是数据源的样子:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [results count];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    [lock lock];
    if (indexPath.row < [results count]) {
        cell.textLabel.text = [results objectAtIndex:indexPath.row];
    }
    [lock unlock];

    return cell;
}

以下是我用来更新表格的代码:

[tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

它完全解决了崩溃问题。但是,我认为它可能效率不高,因为每次要求一个单元格时,数据源都必须锁定/解锁。我上面提到的情况并不经常发生。有没有人更好地了解如何有效地解决这个问题?

非常感谢!

4 个答案:

答案 0 :(得分:4)

不要尝试从后台线程更新UI。它不起作用。

答案 1 :(得分:2)

为什么要为此使用单独的线程?搜索需要多长时间? 0.1秒?这与用户停止输入并查看屏幕所花费的时间相比如何?

不要过于复杂化! (如果您的搜索时间超过0.7秒且无法优化,我会将其取回; - )

答案 2 :(得分:1)

这里有一个有用的答案,这是我对另一个类似问题的回答。

在不了解您的应用程序的情况下,我认为更好的解决方案之一是将数组保留在主线程上,并在另一个线程需要进行更改时将其分派回来。像这样:

dispatch_async(dispatch_get_main_queue(), ^{
                [array addObject:object];
                [tableView reloadData];
            });

当然,使用调度API可以使事情变得更复杂,但它确实可以处理锁定和一切。绝对比使用NSLock更优雅。它只适用于iOS 4或更高版本。

答案 3 :(得分:0)

您无法在后台线程中更新UI。

使用 Grand Central Displatch

我在这里解释了

https://stackoverflow.com/a/15469885/1239426