Ios 缓存URL图像iphone UITableview

Ios 缓存URL图像iphone UITableview,ios,iphone,uitableview,cocoa-touch,image-caching,Ios,Iphone,Uitableview,Cocoa Touch,Image Caching,我正在寻找一个关于如何将从url加载的图像缓存到uitableview单元格的教程 我在这里找到了一个例子 但代码是不完整的。我是一名objective c新手,因此我发现很难填补缺少的部分。这里有一个很好的工作示例 我为我一直在开发的一个应用程序写了这篇文章(其中的概念和一些代码取自Lane Roath优秀的UIImageView+缓存类别)。它也使用类,这些类非常好。这肯定是可以改进的。。例如,允许在不再需要时取消请求,或者利用通知userInfo允许更精确的UI更新。。但就我的目的而言,

我正在寻找一个关于如何将从url加载的图像缓存到uitableview单元格的教程

我在这里找到了一个例子


但代码是不完整的。我是一名objective c新手,因此我发现很难填补缺少的部分。

这里有一个很好的工作示例

我为我一直在开发的一个应用程序写了这篇文章(其中的概念和一些代码取自Lane Roath优秀的UIImageView+缓存类别)。它也使用类,这些类非常好。这肯定是可以改进的。。例如,允许在不再需要时取消请求,或者利用通知userInfo允许更精确的UI更新。。但就我的目的而言,它工作得很好

@implementation ImageFetcher
#define MAX_CACHED_IMAGES 20
static NSMutableDictionary* cache = nil;

+ (void)asyncImageFetch:(UIImage**)anImagePtr withURL:(NSURL*)aUrl {

    if(!cache) {
        cache = [[NSMutableDictionary dictionaryWithCapacity:MAX_CACHED_IMAGES] retain];
    }

    UIImage* newImage = [cache objectForKey:aUrl.description];
    if(!newImage) { // cache miss - doh!
        ASIHTTPRequest *imageRequest = [ASIHTTPRequest requestWithURL:aUrl];    
        imageRequest.userInfo = [NSDictionary dictionaryWithObject:[NSValue valueWithPointer:anImagePtr] forKey:@"imagePtr"];
        imageRequest.delegate = self;
        [imageRequest setDidFinishSelector:@selector(didReceiveImage:)];
        [imageRequest setDidFailSelector:@selector(didNotReceiveImage:)];
        [imageRequest startAsynchronous];
    }
    else { // cache hit - good!
        *anImagePtr = [newImage retain];    
    }
}

+ (void)didReceiveImage:(ASIHTTPRequest *)request {
    NSLog(@"Image data received.");
    UIImage **anImagePtr = [(NSValue*)[request.userInfo objectForKey:@"imagePtr"] pointerValue];

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    UIImage *newImage = [[UIImage imageWithData:[request responseData]] retain];

    if(!newImage) {
        NSLog(@"UIImageView: LoadImage Failed");
    }
    else {
        *anImagePtr = newImage;
        // check to see if we should flush existing cached items before adding this new item
        if( [cache count] >= MAX_CACHED_IMAGES)
            [cache removeAllObjects];

        [cache setValue:newImage forKey:[request url].description];

        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc postNotificationName: @"ImageDidLoad" object: self userInfo:request.userInfo];
    }

    [pool drain];
}
您可以按如下方式调用此代码:

[ImageFetcher asyncImageFetch:&icon withURL:url];
我还使用通知,不管是好是坏,让对应UIImage的任何所有者知道他们应该何时重新显示—在本例中,它位于tableView上下文中:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(imageDidLoad:) name:@"ImageDidLoad" object:nil];
}

- (void)imageDidLoad:(NSNotification*)notif {
    NSLog(@"Received icon load notification.");
    // reload table view so that new image appears.. would be better if I could
    // only reload the particular UIImageView that holds this image, oh well...
    [self.tableView reloadData];
}

- (void)dealloc {
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc removeObserver:self];
        // ...
}

您还可以尝试使用sharp fellows在编写的EgoImage库来完成此任务。它使用非常简单,在幕后高效地使用缓存,非常适合满足您的需求


以下是库的示例,其中包括一个演示应用程序。

您可能还需要查看。它附带了一个与UIImageView兼容的视图类,它透明地执行所有缓存,并且适合在滚动性能非常重要的UITableViewCells中使用。

下面是一个使用NSCache的简单ImageCache实现。ImageCache是一个Singleton

ImageCache.h

    #import <Foundation/Foundation.h>

    @interface ImageCache : NSObject

    @property (nonatomic, retain) NSCache *imgCache;


    #pragma mark - Methods

    + (ImageCache*)sharedImageCache;
    //- (void) AddImage:(NSString *)imageURL: (UIImage *)image;
   - (void) AddImage:(NSString *)imageURL withImage:(UIImage *)image;
    - (UIImage*) GetImage:(NSString *)imageURL;
    - (BOOL) DoesExist:(NSString *)imageURL;

    @end
示例

UIImage *image;

    // 1. Check the image cache to see if the image already exists. If so, then use it. If not, then download it.

    if ([[ImageCache sharedImageCache] DoesExist:imgUrl] == true)
    {
        image = [[ImageCache sharedImageCache] GetImage:imgUrl];
    }
    else
    {
        NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: imgUrl]];
        image = [[UIImage alloc] initWithData:imageData];

        // Add the image to the cache 
        //[[ImageCache sharedImageCache] AddImage:imgUrl :image];

        [[ImageCache sharedImageCache] AddImage:imgUrl withImage:image];
    }

这里还有一个提示:如果您正在缓存大量图像或大型图像,因此使用了大量内存,则可能需要创建一个“+(void)flushCache”方法,该方法执行“[cache removeAllObjects]”,以便根据需要从didReceiveMemoryWarning方法中调用它。。这将释放所有内存。iOS 5的更新版本:
git clonehttp://ezekiel.vancouver.wsu.edu/~cs458/demos/yellowjackers/.git
在ImageCache.m方法中有一个输入错误:
-(void)AddImage:(NSString*)imageURL:(NSString*)image
应该是
-(void)AddImage:(NSString*)imageURL:(UIImage*))图像
(NSString*)图像
应该是
(UIImage*)图像
。感谢您的精彩回答。它充满了需求。信息非常有帮助的回答+1,1问题此缓存图像存储在哪里我已检查了不包含它的文档目录,其他问题是此代码如何删除此缓存图像或不需要这样做?做得好。但我建议1。遵循方法的camelCase命名约定;二,。使用
dispatch\u once
实例化你的singleton(请参阅讨论。嗨,我和你在这里做的一样,但它不起作用。我想用NSCache在customCell中显示缩略图。这是我的帖子,请看一下。谢谢。你可以使用像UIImageLoader()这样的帮助程序,而不是自己实现所有内容UIImageLoader只有两个文件,使用起来非常简单。repo中也有一个很好的示例。
UIImage *image;

    // 1. Check the image cache to see if the image already exists. If so, then use it. If not, then download it.

    if ([[ImageCache sharedImageCache] DoesExist:imgUrl] == true)
    {
        image = [[ImageCache sharedImageCache] GetImage:imgUrl];
    }
    else
    {
        NSData *imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: imgUrl]];
        image = [[UIImage alloc] initWithData:imageData];

        // Add the image to the cache 
        //[[ImageCache sharedImageCache] AddImage:imgUrl :image];

        [[ImageCache sharedImageCache] AddImage:imgUrl withImage:image];
    }