Iphone 为UITableView存储来自web的图像

Iphone 为UITableView存储来自web的图像,iphone,ios,image,uitableview,web,Iphone,Ios,Image,Uitableview,Web,我有一个UITableView,自定义单元格显示文本,右边有一个image.image。 起初,一切都很好,但后来我注意到当滚动时,整个tableview都落后了。这是因为该应用程序可能在重新使用手机时,在手机进入屏幕时下载了手机图像。我添加了一个NSCache来存储下载的图像,并告诉cellforrowatinexpath加载图像名(如果存在),否则,再次从internet下载。然而,缓存是如此短暂的存储,如果我用home按钮退出应用程序,然后重新进入,那么只剩下部分图像,并且必须再次下载图像

我有一个UITableView,自定义单元格显示文本,右边有一个image.image。 起初,一切都很好,但后来我注意到当滚动时,整个tableview都落后了。这是因为该应用程序可能在重新使用手机时,在手机进入屏幕时下载了手机图像。我添加了一个NSCache来存储下载的图像,并告诉cellforrowatinexpath加载图像名(如果存在),否则,再次从internet下载。然而,缓存是如此短暂的存储,如果我用home按钮退出应用程序,然后重新进入,那么只剩下部分图像,并且必须再次下载图像

我试图找到一种比缓存更长期地存储图像的最佳方法。我读过一些关于NSDirectory和存储在应用程序库中的内容,但还没有弄明白

我认为,最合乎逻辑的解决方案是这样做:

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

     /*stuff*/

    NSString *imageName = [dictionary objectForKey:@"Image"];
    UIImage *image = [--Cache-directory-- objectForKey:imageName]; //Try to get it from cache

    if(image) //If image was received from cache:
    {
        cell.imageView.Image = image;
    }
    else //If not in cache:
    {
        image = [--local-directory-- objectForKey:imageName]; //Check some local directory

        if(image) //If image received from directory:
        {
            cell.imageView.Image = image;
            // + Also save it to the cache?
        }
        else //If image was in neither cache or local directory, get it from the website with given URL
        {
            image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]];
            //Then save to cache and to file?
        }
    }


}
这些图像很少被更改或关闭,但我不愿意在应用程序中预先实现它们,因此每次添加图像时我都必须发布更新


这在我看来是合乎逻辑的。我走对了吗?我如何调用本地目录?比如,如果我将图像添加到NSDirectory对象或其他对象,这不是每次都会重置吗?如何访问本地文件夹?

我最近正在处理UITableView,遇到了类似的问题。我使用的一个解决方法是,由于图像很小,我认为您的图像也很小,并且有唯一的名称,我将它们存储在应用程序的本地文档文件夹中,并使用核心数据保存对图像位置的引用。我从那个位置加载图像。如果图像发生变化,我会改变这些图像。不过,这可能不是最优雅的方法。只是一个建议

至于访问本地应用程序目录,我使用这个

// INSTANCE METHOD - get the path and file name for the saved plist
- (NSString *)getFileLocation:(NSString *)location {
    // Get all available file system paths for the user
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    // Get the "Documents" directory path - it's the one and only on iPhone OS
    NSString *documentsPath = [paths objectAtIndex:0];

    // Specify the file name, appending it to documentsPath above
    NSString *savedFileName = [documentsPath stringByAppendingPathComponent:location];
    NSLog(@"File Location %@", location);
    // We're done
    return savedFileName;
}

似乎最好的解决方案可能是使用核心数据。但与@Anachid建议的不同,你可以像以前一样从互联网上加载它们,然后将它们放入核心数据目录。我建议你上网,而不是把它们放在你的解决方案中,因为你必须更新才能得到新的图片。然后,您可以根据需要使用它们。

无需保存所有这些图像

如果您是从url获取图像,那么只需使用

使用该链接获取ASyncImageView的h和m文件,并将它们保存在项目中

在执行此操作的任何位置导入h文件

#import 'AsyncImageView.h'
然后使用以下代码

[[AsyncImageLoader sharedLoader] cancelLoadingURL:image.imageURL];

image.imageURL=[NSURL URLWithString:@"imageURL"];

您从错误的方向攻击问题。。。 问题是tableView落后了。 原因是您在主线程中下载图像。 即使从光盘上读取图像,u仍然无法获得最佳的滚动性能

所以一定不要阻塞你的主线程。要做到这一点,你可以异步下载图片,或者使用GCD在另一个线程中下载

像这样:

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

     /*stuff*/  

     // this will block your main thread, bad idea..
     //image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]];

     // instead call it in a separate thread  
     dispatch_queue_t imgDownloaderQueue = dispatch_queue_create("imageDownloader", NULL);
         dispatch_async(imgDownloaderQueue, ^{
         // download the image in separate thread
         UIImage *image = [[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:imageURL]] autorelease];
         dispatch_queue_t main_queue = dispatch_get_main_queue();
         dispatch_sync(main_queue, ^{                        
            // this is called in the main thread after the download has finished, here u update the cell's imageView with the new image
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.imageView.image = image;
        });
    });
    dispatch_release(imgDownloaderQueue);
}

刚刚记住:当您执行web服务拉取时,您不是以JSON等格式在本地存储所有数据吗?如果是这样的话,图像不是以二进制数据的形式返回JSON值吗?如果是这样的话,那么我不明白为什么每次回收一个单元格时都要重新加载图像。如果您不随web服务一起返回数据,也许您可以尝试一下,看看是否能获得更好的响应时间。我使用JSON是,但仅获取图像的名称以及其他数据标题、描述,如1.png、2.png等。然后,我使用UIImage*image=[[UIImage alloc]initWithData:[NSData dataWithContentsOfURL:[@www.example.com/%@,imageName]];嗯,不完全像那样,但也有一些字符串解析的东西..但我只知道名称。我应该将整个图像保存在数据库中吗?Is最多可能是50个图像,每个图像的像素为500*150。好的..是的,我同意。我试着阅读一些核心数据,但我发现很难快速学习..你知道任何教程吗,或short但是thourough关于它的文章?我不知道从哪里开始,我想我误解了核心数据的使用,以及它实际上是什么。基本上,你建立了数据模型,然后通过你的应用程序用你的数据填充它。这意味着你的应用程序需要从网络上获取每个新启动的图片,并将它们加载到核心数据中.从这一点上,你可以从中获取数据。有很多关于它的资料,这取决于你想要什么,我在youtube上看到了一些很好的教程。好的,我会尝试一下,但这不会导致每次启动时tableview都是空的,并且最终会自动填充?图像很少会被更新,我不想看到除第一次启动应用程序外,任何时候都可以加载没有图像的单元格。或者至少,每次您退出该过程时看起来都是这样。这实际上效果很好!有没有办法让图像一准备好就加载,而不是等到单元格运行后才加载
她重新进入屏幕了吗?或者我可以为前8行设置viewDidLoad中的图像吗?您可以为前8行设置viewDidLoad中的图像。cancelLoadingUrl所做的就是在添加它之前确保它不在那里。