- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我有一个 UITableView,它在每一行中显示与联系人关联的图像。在某些情况下,这些图像是在第一次显示时从地址簿联系人图像中读取的,并且在没有这些图像的情况下,它们是基于存储数据呈现的化身。我目前使用 GCD 在后台线程上更新这些图像。但是,这会按照请求的顺序加载图像,这意味着在快速滚动期间队列会变得很长,而当用户停止滚动时,当前单元格是最后得到更新的。在 iPhone 4 上,这个问题并不明显,但我很想支持旧硬件并正在 iPhone 3G 上进行测试。延迟是可以容忍的,但非常明显。
让我印象深刻的是,后进先出堆栈似乎可以在很大程度上解决这个问题,因为每当用户停止滚动时,这些单元格将是下一个要更新的单元格,然后其他当前不在屏幕上的单元格将被更新更新。 Grand Central Dispatch 可以实现这样的事情吗?还是不太繁琐而无法以其他方式实现?
请注意,顺便说一句,我正在将 Core Data 与 SQLite 存储一起使用,并且我没有使用 NSFetchedResultsController
,因为必须遍历多对多关系才能加载数据这个观点。 (据我所知,这排除了使用 NSFetchedResultsController 的可能性。)
[我发现 NSFetchedResultsController 可以用于多对多关系,尽管官方文档似乎是这么说的。但我还没有在这种情况下使用它。]
补充:请注意,虽然主题是“如何使用 GCD 创建后进先出堆栈”,但实际上我只是想解决上述问题,可能会有是一种更好的方法。我非常愿意接受 timthetoolman 提出的以另一种方式解决问题的建议;如果这样的建议最终是我使用的,我将认识到原始问题的最佳答案以及我最终实现的最佳解决方案......:)
最佳答案
由于设备的内存限制,您应该按需在后台 GCD 队列中加载图像。在 cellForRowAtIndexPath: 方法中检查您的联系人图像是否为零或已被缓存。如果图像为 nil 或不在缓存中,请使用嵌套的 dispatch_async 从数据库加载图像并更新 tableView 单元格。
- (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];
}
// If the contact object's image has not been loaded,
// Use a place holder image, then use dispatch_async on a background queue to retrieve it.
if (contact.image!=nil){
[[cell imageView] setImage: contact.image];
}else{
// Set a temporary placeholder
[[cell imageView] setImage: placeHolderImage];
// Retrieve the image from the database on a background queue
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
UIImage *image = // render image;
contact.image=image;
// use an index path to get at the cell we want to use because
// the original may be reused by the OS.
UITableViewCell *theCell=[tableView cellForRowAtIndexPath:indexPath];
// check to see if the cell is visible
if ([tableView visibleCells] containsObject: theCell]){
// put the image into the cell's imageView on the main queue
dispatch_async(dispatch_get_main_queue(), ^{
[[theCell imageView] setImage:contact.image];
[theCell setNeedsLayout];
});
}
});
}
return cell;
}
WWDC2010 session 视频“Introducing Blocks and Grand Central Dispatch”也展示了使用嵌套 dispatch_async 的示例。
另一个潜在的优化可能是在应用程序启动时开始在低优先级后台队列中下载图像。即
// in the ApplicationDidFinishLaunchingWithOptions method
// dispatch in on the main queue to get it working as soon
// as the main queue comes "online". A trick mentioned by
// Apple at WWDC
dispatch_async(dispatch_get_main_queue(), ^{
// dispatch to background priority queue as soon as we
// get onto the main queue so as not to block the main
// queue and therefore the UI
dispatch_queue_t lowPriorityQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)
dispatch_apply(contactsCount,lowPriorityQueue ,^(size_t idx){
// skip the first 25 because they will be called
// almost immediately by the tableView
if (idx>24){
UIImage *renderedImage =/// render image
[[contactsArray objectAtIndex: idx] setImage: renderedImage];
}
});
});
通过这种嵌套调度,我们在极低优先级队列上渲染图像。将图像渲染放在后台优先级队列中将允许从上面的 cellForRowAtIndexPath 方法渲染的图像以更高的优先级渲染。因此,由于队列优先级的不同,您将有一个“穷人”后进先出法。
祝你好运。
关于iphone - GCD 的后进先出堆栈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7567827/
几个月前,我做了一个功能,我的应用程序正在等待用户文档并做出相应的响应。直到我对项目进行优化并将其更新到最新版本之前,它一直是一种魅力。 如果存在用户文档,则流将产生该文档并关闭该流。 如果云Fire
Stack Overflow 有几个 examples其中函数首先获得可升级锁,然后通过升级获得独占访问。我的理解是,如果不小心使用,这可能会导致死锁,因为两个线程可能都获得了可升级/共享锁,然后都尝
这个问题在这里已经有了答案: MVC 4 Code First ForeignKeyAttribute on property ... on type ... is not valid (1 个回答
以下是部分代码。我需要在 finally 子句中关闭资源。我需要先调用 closeEntry() 还是 close()?我收到一些错误消息。 Error closing the zipoutjava.
我想使用 RxJS-DOM 观察 mousewheel 事件,这样当第一个事件触发时,我转发它然后删除所有值,直到后续值之间的延迟超过先前指定的持续时间。 我想象的运算符可能看起来像: Rx.DOM.
版本似乎与安装的不同。 我在 npm install 上收到警告 我将二进制文件安装到我的家庭/开发目录中,但它不适用于 sudo。所以我安装了apt。 (注意:我并没有真正安装,我提取并将路径放在/
我正在尝试展示 GAN 网络在某些指定时期的结果。打印当前结果的功能以前与 TF 一起使用。我需要换成 pytorch。 def show_result(G_net, z_, num_epoch, s
我是一名优秀的程序员,十分优秀!