iOS GCD(二)

上篇记录了GCD的各种基本使用方法及特点,下面是GCD在项目中的常用场景


1、创建单例 dispatch_once

static People *sharePeople = nil;
+ (instancetype)sharePeople{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSLog(@"oncetoken");//这里的代码只会执行一次
        sharePeople = [[self alloc]init];
    });
    return sharePeople;
}

2、延迟执行   dispatch_after (异步)

函数原型

参数 when 延迟执行的时间

参数 quene 在哪个队列中执行

参数 block 延迟执行的内容

dispatch_after(dispatch_time_t when,
	dispatch_queue_t queue,
	dispatch_block_t block);
    NSLog(@"开始");
    double delayInSeconds = 2.0;
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW,delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, mainQueue, ^{
        NSLog(@"延时执行的2秒");
    });
    NSLog(@"结束");
执行结果:

2016-12-27 15:37:32.509 GCD[1547:228385] 开始
2016-12-27 15:37:32.509 GCD[1547:228385] 结束
2016-12-27 15:37:34.510 GCD[1547:228385] 延时执行的2秒

注意:延迟执行在iOS中一般还可以通过下面的方法或者NSTimer来实现

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;

但这个方法并不是安全的,因为这个方法或者是NSTimer都需要有一个runloop来实现,而只有主线程在创建的时候回默认自动运行一个runloop,普通的子线程是没有的,一旦这两种方式在子线程中调用,则延迟方法里面的内容就永远不会执行。

相对来说GCD是安全的

3、并发地执行循环迭代 dispatch_apply

         代替for循环  要求,循环次数固定并且循环执行的次序无关,这是可以用dispatch_apply提高效率(并发执行)

         原来的for循环

int i;
    int count = 10;
    for (i = 0; i < count; i++) {
        printf("%d  ",i);
    }
这是输出

0  1  2  3  4  5  6  7  8  9  

同dispatch_apply代替

 // 获得全局并发queue
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    size_t count = 10;
    dispatch_apply(count, queue, ^(size_t i) {
        printf("%zd ", i);
    });
可能就会输出

0 1 3 2 4 5 6 8 7 9  

4、在子线程中调用下载图片等耗时操作,下载完成后在主线程刷新界面

// 异步下载图片
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURL *url = [NSURL URLWithString:@"http://image.baidu.com/search/detail?ct=503316480&z=0&tn=baiduimagedetail&ipn=d&cl=2&cm=1&sc=0&lm=-1&ie=gbk&pn=0&rn=1&di=20652390440&ln=30&word=ͼƬ&os=3812566282,1648699000&cs=214931719,1608091472&objurl=http%3A%2F%2F4493bz.1985t.com%2Fuploads%2Fallimg%2F150127%2F4-15012G52133.jpg&bdtype=0&simid=3354004378,369260611&pi=0&adpicid=0&fr=ala&ala=1&alatpl=others&pos=1"];
        UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
        
        // 回到主线程显示图片
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = image;
        });  
    });

这里可能会有这种情况,某界面需要两张或多张图片,当所有的图片加载完成后才刷新界面,这时可以用 Dispatch Group来实现

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 异步下载图片
    dispatch_async(queue, ^{
        // 创建一个组
        dispatch_group_t group = dispatch_group_create();
        
        __block UIImage *image1 = nil;
        __block UIImage *image2 = nil;
        
        // 关联一个任务到group
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 下载第一张图片
            NSString *url1 = @"http://car0.autoimg.cn/upload/spec/9579/u_20120110174805627264.jpg";
            image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url1]]];
        });
        
        // 关联一个任务到group
        dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 下载第一张图片
            NSString *url2 = @"http://hiphotos.baidu.com/lvpics/pic/item/3a86813d1fa41768bba16746.jpg";
            image2 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url2]]];
        });
        
        // 等待组中的任务执行完毕,回到主线程执行block回调
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            self.imageView1.image = image1;
            self.imageView2.image = image2;
            
            // 千万不要在异步线程中自动释放UIImage,因为当异步线程结束,异步线程的自动释放池也会被销毁,那么UIImage也会被销毁
        });
    });




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值