NSOperationQueue 和 UITableView
我正在从 SQLite 数据库加载一些数据以显示在 UITableView
中。为了确保用户不被阻止并且表快速显示,我创建了一个队列并添加要在后台执行的数据库操作。
添加很好并且工作正常,但由于某种原因,随机某些行没有用数据更新!
我知道数据设置正确,因为当我单击该行时,该行会使用我的数据进行更新,但我似乎找不到更新 UI 的方法!我已经尝试了所有方法,包括使用 setNeedDisplay
等,但没有任何效果!
这是我的代码:
- (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];
}
I'm loading some data from a SQLite database to be displayed in a 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! I've tried everything including using setNeedDisplay
and so on but nothing works!
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];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的逻辑有缺陷,我认为你会经历糟糕的表现以及你已经遇到的问题。最好启动一个整体操作来加载所有数据或至少部分数据,然后要求表在完成时重新加载。
您现在执行此操作的方式是,每个单元格都访问数据库并选择一行,而不是在任何地方缓存此数据(这意味着如果它滚动到视图之外然后再次返回,则必须再次访问数据库)。此外,当操作完成时,不会在此单元格上调用绘图代码(这就是为什么在单击它导致绘图调用之前它不会显示)。
您应该将所有这些数据加载到自定义对象数组中。加载后,您应该重新加载表格并使用新填充的数组来设置单元格中的属性。
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.
您正在从后台线程更新用户界面,这是错误的。所有用户界面工作必须在主线程上完成。尝试将与
cell
的所有交互移至主线程,并在NSDictionary
中传递来自后台线程的数据。请参阅 performSelectorOnMainThread:withObject:waitUntilDone:。另请阅读 线程和用户界面。
@theChrisKent 对性能提出了很好的观点,尽管这个线程问题更可能是导致您不稳定行为的原因。
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 anNSDictionary
.See performSelectorOnMainThread:withObject:waitUntilDone:. Also read Threads and Your User Interface in Apple's Threading Programming Guide.
@theChrisKent made good points about performance, though this threading issue is more likely the cause of your erratic behavior.