频道栏目
首页 > 程序开发 > 移动开发 > IOS > 正文
ios多线程 -- GCD 常见用法
2016-06-28 09:51:40         来源:不积跬步  
收藏   我要投稿

GCD 通信操作

#pragma mark - GCD 通信
- (void)sendMessage{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //耗时操作
        [self downLoad:@"https://..."];

        //回主队列刷新数据
        dispatch_async(dispatch_get_main_queue(), ^{
            //刷新UI操作
        });
    });
}

延时操作
iOS常见的延时执行有2种方式
(1)调用NSObject的方法

// 2秒后再调用self的run方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0];

(2)使用GCD函数

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    // 2秒后异步执行这里的代码...
});

代码演示:

#pragma mark - GCD 延迟
- (void)delayModel:(CGFloat)time{
    // 经过延迟 time 秒后,回到当前线程,执行。不会卡住当前线程
    // 该方法在那个线程调用,那么run就在哪个线程执行(当前线程),通常是主线程
    //[self performSelector:@selector(downLoad:) withObject:@"delayModel" afterDelay:time];

    // GCD 实现
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), queue, ^{
        [self downLoad:@"GCD---delayModel"];
    });
}

延时操作
GCD延时操作

一次性代码

#pragma mark - GCD 一次性代码
- (void)onceCore{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    // 只执行1次的代码(这里面默认是线程安全的)
        [self downLoad:@"onceCore"];
    });
}

一次性代码

队列组

#pragma mark - GCD 队列组
- (void)groupQueue{
    // 1 获取全局队列
    /**
     * 优先级
     * DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
     * DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中)
     * DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
     * DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后台
     */
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // 2 获取队列组
    dispatch_group_t group = dispatch_group_create();

    // 3 下载图片1
    //__block 修饰的值才能在 block 中改
    __block UIImage *image1 = nil;
    dispatch_group_async(group, queue, ^{
        //下载图片
        NSString *urlStr = @"https://b.hiphotos.baidu.com/image/pic/item/cdbf6c81800a19d8c58c800431fa828ba61e4627.jpg";
        NSURL *url = [NSURL URLWithString:urlStr];
        NSData *data = [NSData dataWithContentsOfURL:url];
        image1 = [UIImage imageWithData:data];
    });

    // 4 下载图片2
    __block UIImage *image2 = nil;
    dispatch_group_async(group, queue, ^{
        //下载图片
        NSString *urlStr = @"https://b.hiphotos.baidu.com/image/w%3D230/sign=fbc72e14362ac65c67056170cbf2b21d/e4dde71190ef76c666af095f9e16fdfaaf516741.jpg";
        NSURL *url = [NSURL URLWithString:urlStr];
        NSData *data = [NSData dataWithContentsOfURL:url];
        image2 = [UIImage imageWithData:data];
    });


    // 5 合并图片1, 2
    dispatch_group_notify(group, queue, ^{
        //获取图形上下文
        UIGraphicsBeginImageContextWithOptions(image1.size, NO, 0.0);
        //绘制第一张图片
        [image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)];
        //绘制第二张图片
        [image2 drawInRect:CGRectMake(0, 0, image2.size.width * 4, image2.size.height * 3)];
        //得到上下文的新图片
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        //关闭上下文
        UIGraphicsEndImageContext();

        //回到主线程刷新界面
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = newImage;
        });
    });

}

 

补充:

有这么1种需求:

首先:分别异步执行2个耗时的操作

其次:等2个异步操作都执行完毕后,再回到主线程执行操作



如果想要快速高效地实现上述需求,可以考虑用队列组

dispatch_group_t group =  dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 执行1个耗时的异步操作
});

dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // 执行1个耗时的异步操作
});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 等前面的异步操作都执行完毕后,回到主线程...
});
点击复制链接 与好友分享!回本站首页
相关TAG标签 线程 常见
上一篇:IOS 蓝牙介绍
下一篇:iOS控件之UIPageControl
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站