美文网首页
『ios』GCD补习 dispatch block

『ios』GCD补习 dispatch block

作者: butterflyer | 来源:发表于2018-10-30 16:58 被阅读13次
image.png

不要走的太快,慢慢来。

这几天翻api,看到了这个dispatch文件,对里面的block比较感兴趣,所以查了下资料学习了一下。用处蛮大的。

按照惯例先上头文件方法。

创建block的方法
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
创建block的方法,并可以指定优先级
dispatch_block_t
dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
        dispatch_qos_class_t qos_class, int relative_priority,
        dispatch_block_t block);
创建,同步执行,并从指定的块和标志释放调度块。
void
dispatch_block_perform(dispatch_block_flags_t flags,
        DISPATCH_NOESCAPE dispatch_block_t block);
同步等待,直到指定的调度块的执行完成,或者直到超过指定的超时时间。
long
dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);

当指定的调度块的执行完成时,安排通知块被提交给队列。
void
dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
        dispatch_block_t notification_block);
异步取消指定的分派块
void
dispatch_block_cancel(dispatch_block_t block);
测试给定的调度块是否被取消
long
dispatch_block_testcancel(dispatch_block_t block);

上面就是block.h文件中的所有方法

dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block)

dispatch_block_flags_t 的枚举如下:

DISPATCH_ENUM(dispatch_block_flags, unsigned long,
    DISPATCH_BLOCK_BARRIER
            DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x1,
    DISPATCH_BLOCK_DETACHED
            DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x2,
    DISPATCH_BLOCK_ASSIGN_CURRENT
            DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x4,
    DISPATCH_BLOCK_NO_QOS_CLASS
            DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x8,
    DISPATCH_BLOCK_INHERIT_QOS_CLASS
            DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x10,
    DISPATCH_BLOCK_ENFORCE_QOS_CLASS
            DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x20,
);
DISPATCH_BLOCK_BARRIER 保证代码块用于原子性,代码块的代码未执行结束前,下一次调用将进入一个FIFO的等待队列,等待本次代码块执行结束,使用较为安全,若不考虑线程安全可使用DISPATCH_BLOCK_DETACHED

dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,

    dispatch_qos_class_t qos_class, int relative_priority,
    dispatch_block_t block);

dispatch_qos_class_t 枚举如下

QOS_CLASS_USER_INTERACTIVE:user interactive 等级表示任务需要被立即执行,用来在响应事件之后更新 UI,来提供好的用户体验。这个等级最好保持小规模。

QOS_CLASS_USER_INITIATED:user initiated 等级表示任务由 UI 发起异步执行。适用场景是需要及时结果同时又可以继续交互的时候。

QOS_CLASS_DEFAULT:default 默认优先级

QOS_CLASS_UTILITY:utility 等级表示需要长时间运行的任务,伴有用户可见进度指示器。经常会用来做计算,I/O,网络,持续的数据填充等任务。这个任务节能。

QOS_CLASS_BACKGROUND:background 等级表示用户不会察觉的任务,使用它来处理预加载,或者不需要用户交互和对时间不敏感的任务。

QOS_CLASS_UNSPECIFIED:unspecified 未指明

该看看具体的实现了

dispatch_queue_t concurrentQuene = dispatch_queue_create("concurrentQuene", DISPATCH_QUEUE_CONCURRENT);

dispatch_block_t block = dispatch_block_create(0, ^{
    NSLog(@"normal do some thing...");
});
dispatch_async(concurrentQuene, block);

//
dispatch_block_t qosBlock = dispatch_block_create_with_qos_class(0, QOS_CLASS_DEFAULT, 0, ^{
    NSLog(@"qos do some thing...");
});
dispatch_async(concurrentQuene, qosBlock);

dispatch_block_perform(dispatch_block_flags_t flags,

    DISPATCH_NOESCAPE dispatch_block_t block);

    dispatch_block_t block = dispatch_block_create(DISPATCH_BLOCK_DETACHED, ^{
        NSLog(@"normal do some thing...");
    });
//    dispatch_async(concurrentQuene, block);
    dispatch_block_perform(0, block);

dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout)

这是监听block执行是否结束的一种方法

dispatch_queue_t concurrentQuene = dispatch_queue_create("concurrentQuene", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrentQuene, ^{
    dispatch_queue_t allTasksQueue = dispatch_queue_create("allTasksQueue", DISPATCH_QUEUE_CONCURRENT);

    dispatch_block_t block = dispatch_block_create(0, ^{
        NSLog(@"开始执行");
        [NSThread sleepForTimeInterval:3];
        NSLog(@"结束执行");
    });

    dispatch_async(allTasksQueue, block);
    // 等待时长,10s 之后超时
    dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC));
    long resutl = dispatch_block_wait(block, timeout);
    if (resutl == 0) {
        NSLog(@"执行成功");
    } else {
        NSLog(@"执行超时");
    }
});

从这里可以看出 这个函数可以实现跟信号量差不多的功能吧。这个是同步的

dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,

    dispatch_block_t notification_block);
该函数接收三个参数,第一个参数是需要监视的 block,第二个参数是监听的 block 执行结束之后要提交执行的队列 queue,第三个参数是待加入到队列中的 block。 和  dispatch_block_wait 的不同之处在于:dispatch_block_notify 函数不会阻塞当前线程。
这个是异步的
NSLog(@"---- 开始设置任务 ----");
dispatch_queue_t serialQueue =   dispatch_queue_create("com.xh.serialqueue",   DISPATCH_QUEUE_SERIAL);
// 耗时任务
dispatch_block_t taskBlock = dispatch_block_create(0, ^{
    NSLog(@"开始耗时任务");
    [NSThread sleepForTimeInterval:2.f];
    NSLog(@"完成耗时任务");
});

dispatch_async(serialQueue, taskBlock);
// 更新 UI
dispatch_block_t refreshUI = dispatch_block_create(0, ^{
    NSLog(@"更新 UI");
});
// 设置监听
dispatch_block_notify(taskBlock, dispatch_get_main_queue(), refreshUI);
NSLog(@"---- 完成设置任务 ----");

dispatch_block_cancel(dispatch_block_t block)

取消block执行

    dispatch_queue_t serialQueue = dispatch_queue_create("com.xh.serialqueue", DISPATCH_QUEUE_SERIAL);

    // 耗时任务
    dispatch_block_t firstTaskBlock = dispatch_block_create(0, ^{
        NSLog(@"开始第一个任务");
        [NSThread sleepForTimeInterval:1.5f];
        NSLog(@"结束第一个任务");
    });

    // 耗时任务
    dispatch_block_t secTaskBlock = dispatch_block_create(0, ^{
        NSLog(@"开始第二个任务");
        [NSThread sleepForTimeInterval:4.f];
        NSLog(@"结束第二个任务");
    });

    dispatch_async(serialQueue, firstTaskBlock);
    dispatch_async(serialQueue, secTaskBlock);

    // 等待 1s,让第一个任务开始运行
    [NSThread sleepForTimeInterval:1];

    dispatch_block_cancel(firstTaskBlock);
    NSLog(@"尝试过取消第一个任务");

    dispatch_block_cancel(secTaskBlock);
    NSLog(@"尝试过取消第二个任务");

好了基本就这些了。

想要找一群一起进步的人,请加入我

image.png

相关文章

网友评论

      本文标题:『ios』GCD补习 dispatch block

      本文链接:https://www.haomeiwen.com/subject/ehbgtqtx.html