Jay*_*hao 5 multithreading ios
在我的应用程序中,我必须处理来自网络的大量数据并将其解析为优化的本地格式,然后将它们保存到数据库或将其发送到UI(如果有任何UI正在等待该数据).
我知道在主线程中进行大量的解析工作是愚蠢的,因为它会阻塞主线程并使UI交互非常激动.
所以这就是我试图确保UI线程是免费的:
降低所有线程优先级,即
NSOperation.threadPriority=0.1;
NSThread.threadPriority=0.1;
dispatch_async(dispatch_get_global_queue(PRIORITY_LOW));
Run Code Online (Sandbox Code Playgroud)在这两个步骤之后,当在后台线程中完成一些繁重的工作时,UI会更加顺畅,但仍然非常激动.
这个bug看起来像这样:当我滚动一张桌子时非常流畅,突然桌子冻结了大约0.1秒,然后像往常一样顺利地继续.在冻结期间,我可以看到仪器中的CPU爆发.但是在单独的线程视图中,我可以看到主线程正常,几乎没有CPU消耗.
一个好的解决方案是将Grand Central Dispatch (GCD) 和Objective-C 块与本地缓存结合使用。当您的表格单元格加载时,您应该尽快从tableView:cellForRowAtIndexPath:已设置有任何本地保存数据的表格单元格返回。单元格中需要下载数据或进行大量处理的任何部分都应该有一个占位符(例如活动指示器)。繁重的处理或下载将发生在另一个线程上,如下所示:
// ...This code is at the end of tableView:cellForRowAtIndexPath: where cell
// is already set up and you should have access to your cache and your data
// manager object that will do the processing or downloading for you.
// Show the placeholder (it will hide when real data is set)
cell.placeholder.hidden = NO;
// Check if item is local
MyDataItem* item = [myCache objectForKey:itemKey];
if(item != nil)
{
// Item is available locally, set up the cell now
cell.someImageView.image = item.image;
cell.someLabel.text = item.text;
cell.placeholder.hidden = YES;
}
else
{
// Item is not in cache, go and get it ready
[myDataManager goAndGet:itemKey completion:^(MyDataItem* theItem)
{
// Put the item in the cache
[myCache setObject:theItem forKey:itemKey];
// This block will be executed later and the cell may have been reused
// by then, so we need to ask the table view directly for the cell.
// This returns nil if cell is not currently visible.
MyTableCell* theCell = (MyTableCell*)[tableView cellForRowAtIndexPath:indexPath];
// Set up the table cell
if(theCell != nil)
{
myCell.someImageView.image = theItem.image;
myCell.someLabel.text = theItem.text;
myCell.placeholder.hidden = YES;
}
}];
}
return cell;
Run Code Online (Sandbox Code Playgroud)
正如您从上面的代码中看到的,即使需要进行一些繁重的处理,单元格也会很快返回。这使 UI 保持良好且响应灵敏,不会出现任何导致表格视图上滚动不稳定的延迟。数据管理器将使用 GCD 来执行处理,如下所示:
- (void)goAndGet:(NSString*)itemKey completion:(void (^)(MyDataItem* theItem))completionBlock
{
// Note: this uses DISPATCH_QUEUE_PRIORITY_DEFAULT - but you might want to use
// a different queue, probably one you created yourself for these tasks.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
{
// Do heavy processing or downloading here
MyDataItem* item = [heavyProcessor doProcessingForItem:itemKey];
// The completion block must happen on the main queue
dispatch_async(dispatch_get_main_queue(), ^
{
// Call the completion block
completionBlock(item);
});
});
}
Run Code Online (Sandbox Code Playgroud)
请注意,上面的所有代码都假设您使用的是ARC :)
| 归档时间: |
|
| 查看次数: |
1516 次 |
| 最近记录: |