简体   繁体   English

NSOperationQueue和UITableView

[英]NSOperationQueue and UITableView

I'm loading some data from a SQLite database to be displayed in a UITableView . 我正在从SQLite数据库加载一些数据,以显示在UITableView To make sure the user is not blocked and the table is displayed quickly I'm creating a queue and adding the database operation to be executed in the background. 为了确保用户没有被阻塞并且表可以快速显示,我创建了一个队列并添加了要在后台执行的数据库操作。

The add is good and works fine but for some reason randomly some of the rows are not updated with the data! 添加是好的并且可以正常工作,但是由于某些原因,某些行不会随数据一起更新!

I know the data is set correctly as when I click on the row the row is updated with my data but I can't seem to find a way to update the UI! 我知道数据设置正确,因为当我单击该行时,该行将用我的数据进行更新,但是我似乎找不到更新UI的方法! I've tried everything including using setNeedDisplay and so on but nothing works! 我已经尝试了一切,包括使用setNeedDisplay等,但是没有任何效果!

Here is my code: 这是我的代码:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell* cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.textAlignment = UITextAlignmentRight;
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.font = [UIFont systemFontOfSize:14];
    }

    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.textLabel.text = @"Loading ...";
    cell.tag = indexPath.row;

    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self 
                                                                     selector:@selector(setCellData:) 
                                                                       object:cell];

    [queue addOperation:op];
    [op release];

    return cell;
}


- (void) setCellData:(UITableViewCell *)cell{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    sqlite3_stmt            *statement2;

    NSString *sqlStr = [NSString stringWithFormat:@"SELECT * FROM poemdata WHERE catid='%d' GROUP BY poemid LIMIT 1 OFFSET %d",catId,cell.tag];
//  NSLog(@"%@",sqlStr);
    sqlite3_prepare_v2(database, [sqlStr cStringUsingEncoding:NSASCIIStringEncoding], -1, &statement2, nil);

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    if(sqlite3_step(statement2) == SQLITE_ROW){
        cell.textLabel.text = [[NSString alloc] initWithUTF8String: (char *)sqlite3_column_text(statement2, 3)];
        cell.tag = sqlite3_column_int(statement2, 6);
    }else{
        cell.textLabel.text = @"Error";
    }
    sqlite3_finalize(statement2);

    [pool release];
}

Your logic is flawed and I think you will experience terrible performance as well as the problems you are already experiencing. 您的逻辑有缺陷,我认为您将体验到糟糕的性能以及已经遇到的问题。 It would be better to launch an overall Operation to load all your data or at least a portion of your data and then asking the table to reload when it finishes. 最好启动整体操作以加载所有数据或至少部分数据,然后要求表完成时重新加载。

The way you are doing it now is that every cell is hitting the database and selecting one row and not caching this data anywhere (meaning if it scrolls out of view and then back in again it will have to hit the database again). 现在,您的操作方式是每个单元都在访问数据库并选择一行,而不在任何地方缓存该数据(这意味着如果它滚动到视图外然后再次返回,则必须再次访问数据库)。 In addition there is no drawing code called on this cell when the operation finishes (which is why it doesn't show up until you click it causing a draw call). 另外,操作完成时,此单元格上没有调用绘制代码(这就是为什么直到单击它会引起绘制调用后它才会显示的原因)。

You should load all of this data into an array of custom objects. 您应该将所有这些数据加载到自定义对象的数组中。 Once loaded you should reload the table and use the newly filled array to set your properties in the cell. 加载后,您应该重新加载表并使用新填充的数组在单元格中设置属性。

You're updating your user interface from your background thread, which is wrong. 您正在从后台线程更新用户界面,这是错误的。 All user interface work must be done on the main thread. 所有用户界面工作必须在主线程上完成。 Try moving all interaction with cell to the main thread, passing the data from the background thread in an NSDictionary . 尝试将与cell所有交互都移到主线程,将数据从后台线程传递到NSDictionary

See performSelectorOnMainThread:withObject:waitUntilDone: . 请参见performSelectorOnMainThread:withObject:waitUntilDone:。 Also read Threads and Your User Interface in Apple's Threading Programming Guide. 另请参阅《 Apple线程编程指南》中的“ 线程和用户界面 ”。

@theChrisKent made good points about performance, though this threading issue is more likely the cause of your erratic behavior. @theChrisKent很好地说明了性能,尽管此线程问题很可能是您行为失常的原因。

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

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