我有一个rss解析器,一个tableview,其中包含:文本,细节和设置为AccessoryDisclosureIndicator.view的图像.
使用简单的GCD异步加载图像很快:快速滚动数百个结果.没有滞后,如果我有良好的连接就没有错误.
问题是,一瞬间 – 它们在负载上闪烁,因为该单元正在被重用.此外,如果连接不好,它有时会留下散乱的图像但文本/细节是正确的,只有图像是旧的…所以让我重复一遍,文本/细节更新正常,永远不会重新排队错误,只是图像有时很少在错误的连接上排队错误/癫痫发作 – 快速来回滚动.
我的问题,有人可以帮我缓存/标记cell.accs.views吗?我尝试设置cellID但是我的实现有问题.如果连接从不减慢,我的下面的代码工作得很好,重新排队我不介意的单元格只是轻微的闪烁.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; [cell.textLabel setNumberOfLines:3]; cell.textLabel.font = [UIFont boldSystemFontOfSize:14.0]; [cell.detailTextLabel setNumberOfLines:3]; cell.detailTextLabel.font = [UIFont systemFontOfSize:12.0]; cell.detailTextLabel.textColor = [UIColor blackColor]; } RSSItem * rssItem = (RSSItem *)(_rssParser.rssItems)[indexPath.row]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0ul); dispatch_async(queue,^{ //This is what you will load lazily NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:rssItem.imageURL]]; dispatch_sync(dispatch_get_main_queue(),^{ UIImageView *accImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:data ]]; [accImageView setFrame:CGRectMake(0,accImageView.image.size.width,92)]; cell.accessoryView = accImageView; //[cell setNeedsLayout];//not needed }); }); [cell.textLabel setText:rssItem.title]; [cell.detailTextLabel setText:rssItem.summary]; return cell;}
解决方法
两个次要问题:
>请注意,如果使用非常慢的网络,那么当图像返回时,您可以将单元格从屏幕上滚动(例如,想象您向上轻拂滚动视图,然后在图像静止的情况下)正在加载,你把它向后翻了下来).在尝试设置图像之前,您确实应该确保单元格仍然可见.
您可以通过检查(在主队列上)单元格是否可见来执行此操作:
dispatch_async(dispatch_get_main_queue(),^{ UITableViewCell *updateCell = [tableView cellForRowAtIndexPath:indexPath]; if (updateCell != nil) { // update image in `updateCell` } });
请注意,这个UITableView方法cellForRowAtIndexPath
不应该与UITableViewDataSource方法tableView:cellForRowAtIndexPath:
混淆.前者只是检查单元格是否可见,如果是,则返回指向它的指针.显然,后者是您在问题中引用的方法,用于创建和配置表视图单元格.
另请注意,您使用NSIndexPath检查单元格是否仍然可见的这个想法假设在中间时间内表格视图中可能没有插入其他行.这通常不是一个有效的假设,因此您甚至可能必须返回基础模型并重新计算此单元格的indexPath,然后再继续上述逻辑以查看该单元格是否仍然可见.
>您可能不想使用全局队列,因为在网络非常慢的情况下,您的请求可能会开始积压并且您可能最终会遇到大量并发网络请求.这是一个问题,因为(a)系统一次不能执行超过4或5个并发请求; (b)你将耗尽iOS提供的有限数量的工作线程.你真的不应该有超过4或5个并发请求(如果你有更多,你不仅会看到没有性能提升,但它们实际上会阻止并最终超时).我建议您考虑使用NSOperationQueue,将maxConcurrentOperationCount设置为4或5.
此外,这提供了一个最终优化,特别是使这些NSOperation子类请求可取消(并且显然,使取消逻辑实际上取消其中包含的网络请求).因此,如果您快速滚动到表格中的第100行,您实际上不希望让可见单元格等待先前99行的图像下载完成.如果取消滚动屏幕的单元格的图像请求,则可以解决此问题.
如果你想在一个非常慢的网络连接上诊断你的应用程序的行为,我建议你使用网络调节器,它可以让你的Mac模拟从模拟器上的全速到质量差的Edge网络.在Xcode的Xcode菜单中,选择“Open Developer Tool …”,然后选择“More Developer Tools”.登录后,您将看到“Xcode的硬件IO工具”选项.网络调节器工具就在那里.您可以在最糟糕的情况下测试您的应用程序,这可能会让您不仅考虑我上面列出的两个问题,而且还考虑更高级的功能,如图像缓存等.
您真的希望将图像缓存到持久存储,理想情况下是RAM和持久存储.有UIImageView类别可以解决上面的异步问题,并提供一些缓存:您可能考虑的两个是SDWebImage和AFNetworking.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。