如何利用GCD Group批量下载文件

未命名未命名

小引:有时候,我们在开发iOS程序时,需要批量下载一些文件(比如图片),只有当全部文件下载完毕,我们才做相应的处理(界面更新,通知用户等)——也就是说虽然有多个文件在下载,但是我们只需要收到一个全部下载完毕的通知。

在网上搜索了一番,感觉使用GCD的高级功能Group,比较方便。下面写了一个小Demo,实现了多个图片文件的异步并发下载,缓存到本地,并显示到界面中。

参考了唐巧的一篇博文:使用GCD

另外感兴趣的同学可以看看下面几篇GCD相关文章,非常不错:

raywenderlich:Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial

苹果官网:Grand Central Dispatch (GCD) Reference  Concurrency Programming Guide

Demo可以到Github上下载:

 https://github.com/BeyondVincent/DownloadImage_GCD

下面是使用GCD Group的关键代码:

- (IBAction)downloadAction:(UIButton *)sender
{
    [self resetImage];
    self.status.text = @"正在下载";
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t downloadImage = dispatch_group_create();

    for (ImageInfo *info in self.imageList) {
        NSString* imagePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:info.imageName];

        NSFileManager *fileManager = [NSFileManager defaultManager];
        // 如果本地不存在图片,则从网络中下载
        if (![fileManager fileExistsAtPath:imagePath]) {
            dispatch_group_async(downloadImage, queue, ^{
                NSLog(@"Starting image download:%@", imagePath);
                // URL组装和编码
                NSString *urlString = [NSString stringWithFormat:@"%@/%@", self.baseUrl, info.imageName];
                NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
                NSLog(@"image download from url:%@", urlString);

                // 开始下载图片
                NSData *responseData = [NSData dataWithContentsOfURL:url];
                // 将图片保存到指定路径中
                [responseData writeToFile:imagePath atomically:YES];
                // 将下载的图片赋值给info
                info.image = [UIImage imageWithData:responseData];
                NSLog(@"image download finish:%@", imagePath);
            });
        } else { // 将本地图片加载到systemInfo.MyImage
            info.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]];
        }
    }
    dispatch_group_notify(downloadImage, dispatch_get_main_queue(), ^{
        // 图片加载完毕之后,显示出来
        self.status.text = @"图片文件下载并缓存完毕";
        [self showImage];
    });
}

上面关键的代码是dispatch_group_async(并行执行线程1)和dispatch_group_notify(全部下载完毕,由此进行回调通知)。在for语句中循环开启了6个并发任务。当6个任务完成之后,调用showImage方法,将图片显示出来。
下面是运行效果图(第一个图为程序刚刚启动时的效果,第二个为点击开始异步下载图片按钮之后的效果):
QQ20130502-3QQ20130502-3

QQ20130502-2QQ20130502-2
 

在写本Demo的时候,遇到了以下两个问题

  1. 关于图片的加载,UIImage中的imageNamed:方法只能加载程序main bundle中的图片。要想加载Document中的图片,需要使用UIImage的imageWithData方法。更多相关资料可以阅读苹果官方介绍:UIImage
  2. NSURL URLWithString:myString returns Nil。在初始化NSURL实例对象是,一直都返回Nil。后来在这里(Here)发现原来是URL中含有特殊字符,需要进行编码处理,照着链接中的方法搞定。

_________________

本文由破船原创
转载请注明出处:BeyondVincent的博客
_________________

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值