将图像从URL保存到iOS目录

将图像从URL保存到iOS目录,ios,objective-c,Ios,Objective C,我想将大量(800-2000)图像从服务器保存到iPhone应用程序目录(Documents目录) 首先,我必须检查这些图像是否已经在iPhone目录中 我使用此代码下载一幅图像: NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]]; [NSURLConne

我想将大量(800-2000)图像从服务器保存到iPhone应用程序目录(Documents目录)

首先,我必须检查这些图像是否已经在iPhone目录中

我使用此代码下载一幅图像:

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
[NSURLConnection connectionWithRequest:request delegate:self];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:@"pkm.jpg"];
NSData *thedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
[thedata writeToFile:localFilePath atomically:YES];
请帮助我,任何建议: 1.将所有图像以原始名称保存在iPhone目录中,而不是“pkm.jpg” 2.使用名称保存图像:从050520808321_大到050520808350_大 3.检查图像是否已下载,不要再次下载

我知道,也许这不仅仅是个问题。但是一些建议,方向会很好


提前感谢。

我不确定序列化信息的最佳方法(天真地说,您可以将NSDictionary写入磁盘)。我会有一本大字典(它可以被分解成更小的,取决于你怎么做)。NSDictionary将图像名称“05052008321_biger”映射为一个简单的@YES

当应用程序能够下载新图像时,它将从磁盘读取NSDictionary(可以在其他线程中读取),并检查图像名称是否在字典中。这允许快速查找

- (BOOL)checkIfImageHasBeenDownloaded:(NSString *)imageName
{
    return [self.dictionaryNames objectForKey:imageName] != nil;
}
一些反应:

  • 您正在启动一个
    NSURLConnection
    connectionWithRequest
    (它会触发
    NSURLConnectionDataDelegate
    方法),但随后您显然忽略了这一点,并启动了一个
    dataWithContentsOfURL
    。你应该选一个或另一个,但不要两个都选

  • 我建议您采用基于
    NSOperation
    的解决方案,因为您肯定希望(a)享受并发性;但是(b)将并发操作限制在一个合理的数目(比如4或5),否则您的请求将超时并失败

  • 在获取文件名方面,您可以使用
    lastPathComponent
    NSURL
    中检索文件名。(下面使用的我的下载操作实际上会在您不提供显式文件名的情况下自动使用它。)

  • 您还没有说明如何从远程服务器确定文件名列表,因此我们必须了解如何知道要检索的图像

  • 如果这是出于你自己的目的,那也没关系,但我听说苹果拒绝通过手机连接请求太多数据的应用程序(2000张图像肯定符合条件)。坦率地说,即使苹果没有大惊小怪,你也应该在使用用户的大部分数据计划之前询问用户。您可以使用来确定用户是通过wifi连接还是通过蜂窝连接,如果是后者,您可能需要发出警告

  • 但是我会建议这样的东西(假设你有一些
    NSArray
    NSString
    版本的URL…显然,根据你的URL列表的任何形式调整它):

    下载操作可能是这样的。显然,可以使用任何基于
    NSOperation
    的下载器,但我建议您使用一个不会将整个下载加载到内存中的下载器,而是直接将其流式传输到持久存储中的下载器

    如果你不想得到这种幻想,你可以做如下事情:

    NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
    downloadQueue.maxConcurrentOperationCount = 4;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    
    for (NSString *urlString in urlStrings)
    {
        NSURL *url = [NSURL URLWithString:urlString];
        NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
        if (![fileManager fileExistsAtPath:path]) {
            [downloadQueue addOperationWithBlock:^{
                NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
                NSData *data = [NSData dataWithContentsOfURL:url];
                if (data)
                    [data writeToFile:path atomically:YES];
            }];
        }
    }
    

    显然,可以使用任何下载操作类进行下载,但希望您能够了解基本的想法。创建一个基于的下载操作,然后为每个需要下载的文件提交一个。

    您可以使用dropbox或box吗?他们已经为这类东西内置了API?我正在检查。。。谢谢
    NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init];
    downloadQueue.maxConcurrentOperationCount = 4;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
    
    for (NSString *urlString in urlStrings)
    {
        NSURL *url = [NSURL URLWithString:urlString];
        NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
        if (![fileManager fileExistsAtPath:path]) {
            [downloadQueue addOperationWithBlock:^{
                NSString *path = [docsPath stringByAppendingPathComponent:[url lastPathComponent]];
                NSData *data = [NSData dataWithContentsOfURL:url];
                if (data)
                    [data writeToFile:path atomically:YES];
            }];
        }
    }