什么是可重复使用的表格单元格使用NSCache与dispatch_async的正确方法? [英] What is the proper way to use NSCache with dispatch_async in a reusable table cell?

查看:105
本文介绍了什么是可重复使用的表格单元格使用NSCache与dispatch_async的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找一种明确的方式做到这一点,并没有任何地方,举一个例子,解释得很好找到。我希望你能帮助我。

I have been looking for a clear cut way to do this and have not found anywhere that will give an example and explain it very well. I hope you can help me out.

下面是我的code,我现在用:

Here is my code that I am using:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *CellIdentifier = @"NewsCell";
NewsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

// Configure the cell...

NewsItem *item = [newsItemsArray objectAtIndex:indexPath.row];

cell.newsTitle.text = item.title;

NSCache *cache = [_cachedImages objectAtIndex:indexPath.row];

[cache setName:@"image"];
[cache setCountLimit:50];

UIImage *currentImage = [cache objectForKey:@"image"];

if (currentImage) {
    NSLog(@"Cached Image Found");
    cell.imageView.image = currentImage;
}else {
    NSLog(@"No Cached Image");

    cell.newsImage.image = nil;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void)
                   {
                       NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:item.image]];
                       dispatch_async(dispatch_get_main_queue(), ^(void)
                       {
                           cell.newsImage.image = [UIImage imageWithData:imageData];
                           [cache setValue:[UIImage imageWithData:imageData] forKey:@"image"];
                           NSLog(@"Record String = %@",[cache objectForKey:@"image"]);
                       });
                   });
}

return cell;
}

缓存返回nil我。

The cache returns nil for me.

推荐答案

尼廷回答有关如何使用缓存很好的问题。问题是,无论是原来的问题和尼廷的回答您使用GCD,从问题的困扰,其中(a)不提供超过并发请求数控制;和(b)派遣块不是取消。此外,你使用 dataWithContentsOfURL ,这是不可取消。

Nitin answered the question about how to use a cache quite well. The thing is, both the original question and Nitin's answer suffer from a problem that you're using GCD, which (a) doesn't provide control over the number of concurrent requests; and (b) the dispatched blocks are not cancelable. Furthermore, you're using dataWithContentsOfURL, which is not cancelable.

请参阅WWDC 2012的视频异步设计模式与块,GCD和XPC ,部分7,独立的控制和数据流,约48分钟到视频对于为什么这是有问题的,讨论即,如果用户迅速列表向下滚动到第100项中,所有这些其它99的请求将被排队。您可以在极端情况下,可以使用所有可用的工作线程。和IOS只允许五个并发网络请求,无论如何,所以有一个在使用这些线程的所有(如果有的派出块开始无法启动,因为有超过五去要求,你的一些网络请求将启动失败没有任何意义)。

See WWDC 2012 video Asynchronous Design Patterns with Blocks, GCD, and XPC, section 7, "Separate control and data flow", about 48 min into the video for a discussion of why this is problematic, namely if the user quickly scrolls down the list to the 100th item, all of those other 99 requests will be queued up. You can, in extreme cases, use up all of the available worker threads. And iOS only allows five concurrent network requests anyway, so there's no point in using up all of those threads (and if some dispatched blocks start requests that can't start because there are more than five going, some of your network requests will start failing).

因此​​,除了当前的异步执行网络请求,并使用缓存的方法,你应该:

So, in addition to your current approach of performing network requests asynchronously and using a cache, you should:


  1. 使用操作队列,它允许你(一)限制并发请求的数量;和(b)打开了取消操作的能力;

  1. Use operation queue, which allows you to (a) constrain the number of concurrent requests; and (b) opens up the ability to cancel the operation;

使用可取消 NSURLConnection的,太。你可以这样做你自己,贯彻 NSURLConnectionDataDelegate 的方法,或者使用类似AFNetworking或SDWebImage库。

Use a cancelable NSURLConnection, too. You can do this yourself, implementing the NSURLConnectionDataDelegate methods, or use a library like AFNetworking or SDWebImage.

在一个单元重复使用,取消所有待处理请求(如果有的话)为previous细胞。

When a cell is reused, cancel any pending requests (if any) for the previous cell.

这是可以做到的,我们可以告诉你如何正确地做到这一点,但它是一个很多code的。最好的办法是使用许多的UIImageView 类,其中做cacheing之一,也是处理所有这些其他问题。 SDWebImage 的UIImageView 类是pretty不错。它极大地简化了code:

This can be done, and we can show you how to do it properly, but it's a lot of code. The best approach is to use one of the many UIImageView categories, which do cacheing, but also handles all of these other concerns. The UIImageView category of SDWebImage is pretty good. And it greatly simplifies your code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"NewsCell";    // BTW, stay with your standard single cellIdentifier

    NewsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    NewsItem *item = [newsItemsArray objectAtIndex:indexPath.row];

    cell.newsTitle.text = item.title;

    [cell.imageView setImageWithURL:[NSURL URLWithString:item.image]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    return cell;
}

这篇关于什么是可重复使用的表格单元格使用NSCache与dispatch_async的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆