我可以异步UIImageJPEGRepresentation writeToFile吗?

时间:2014-02-10 07:47:54

标签: ios objective-c multithreading

当我从服务器返回图像时,我正在执行以下操作。但是这段代码让我的应用程序瘫痪了。它冻结了用户界面。

这可以在iOS的后台线程上运行吗?我可以使用异步吗?

 if (![NSString isEmpty:user.avatarURL])
 {
     NSString *pathToImage = user.avatarURL;
     NSURL *url = [NSURL URLWithString:pathToImage];
     NSData *data = [NSData dataWithContentsOfURL:url];
     UIImage *image = [[UIImage alloc] initWithData:data];

     [[NSUserDefaults standardUserDefaults] setObject:UIImageJPEGRepresentation(image, 1) forKey:kUserImage];

     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,                                                                                             NSUserDomainMask, YES);
     NSString *documentsDirectory = [paths objectAtIndex:0];
     NSString* path = [documentsDirectory stringByAppendingPathComponent:@"userAvatar.png" ];
     NSData* jpegdata = UIImageJPEGRepresentation(image, 1);
     [jpegdata writeToFile:path atomically:YES];                                           
 }

2 个答案:

答案 0 :(得分:3)

正如@valentin所说,你可以在dispatch_async()调用中的if()语句中做所有事情。

注意我怀疑可能减慢你的速度实际上是-dataWithContentsOfURL:,而不是UIImageJPEGRepresentation(),所以你要确保它在你的dispatch_async里面,而不是在你的外面。

另外,我不清楚你为什么要将数据解压缩成图像,然后重新压缩它。你将会得到这样的工件,并且对于大多数服务,无论如何都会压缩头像图像。

我会做以下事情:

if (user.avatarURL) 
    dispatch_async(dispatch_get_main_queue(), ^{
        NSURL *const imageURL = [NSURL URLWithString:user.avatarURL];
        if (!imageURL)
            return;
        NSData *const imageDdata = [NSData dataWithContentsOfURL:imageURL];
        if (!imageDdata.length)
            return;

        [[NSUserDefaults standardUserDefaults] setObject:imageDdata forKey:kUserImage];

        [imageDdata writeToFile:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"userAvatar.png"] atomically:YES];                                           
    });

答案 1 :(得分:1)

造成最大伤害的线是:

 NSData *data = [NSData dataWithContentsOfURL:url];

因为它从网络下载。您的代码中没有任何内容更新UI,因此它可以在后台线程上运行。只需确保如果您在保存图像后发布通知或随后更新UI,则切换回主线程。