重い検索処理をバックグラウンドスレッドで実行して、その結果をUITableViewに反映させようとしてはまった。
最初は以下のようにしていたが、これは間違い。
- (void)searchStocks:(id)param{ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; while (TRUE) { if (self.thread.isCancelled) { break; } if (self.keyWords != nil) { StockSearchCriteria *criteria = [[StockSearchCriteria alloc] initWithKeyWords:self.keyWords]; self.stockSearchPopoverController.tableViewController.stocks = [StockContainer findByCriteria:criteria]; [self.stockSearchPopoverController.tableViewController.tableView reloadData]; [self.stockSearchPopoverController.tableViewController.tableView performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO ]; self.keyWords = nil; } } [pool release]; }
正しくは以下。
- (void)searchStocks:(id)param{ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; while (TRUE) { if (self.thread.isCancelled) { break; } if (self.keyWords != nil) { StockSearchCriteria *criteria = [[StockSearchCriteria alloc] initWithKeyWords:self.keyWords]; self.stockSearchPopoverController.tableViewController.stocks = [StockContainer findByCriteria:criteria]; [self.stockSearchPopoverController.tableViewController.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO ]; self.keyWords = nil; } } [pool release]; }
ポイントは以下。
・UITableViewのreloadDataはメインスレッドで実行しないといけない。そうしないとtableView:cellForRowAtIndexPathが実行されない。
・reloadDataを実行したらsetNeedsDisplayも実行されるっぽい。