• GCD系列:代码块(dispatch_block)


    dispatch_block

    最显著的功能就是可以取消执行的代码块


    基本函数

    dispatch_block_t dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
    void dispatch_block_perform(dispatch_block_flags_t flags,DISPATCH_NOESCAPE dispatch_block_t block);
    void dispatch_block_cancel(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);
    long dispatch_block_testcancel(dispatch_block_t block);
    

    函数理解

    1.使用dispatch_create创建一个基于GCD的代码块,参数flag,指定代码块的执行环境,block是代码执行体。

    关于flag的定义

    DISPATCH_ENUM_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0)
    DISPATCH_ENUM(dispatch_block_flags, unsigned long
    	DISPATCH_BLOCK_BARRIER = 0x01,
    	DISPATCH_BLOCK_DETACHED = 0x02,
    	DISPATCH_BLOCK_ASSIGN_CURRENT = 0x04,
    	DISPATCH_BLOCK_NO_QOS_CLASS = 0x08,
    	DISPATCH_BLOCK_INHERIT_QOS_CLASS = 0x10,
    	DISPATCH_BLOCK_ENFORCE_QOS_CLASS = 0x20,
    );
    
    • DISPATCH_BLOCK_BARRIER 保证代码块用于原子性,代码块的代码未执行结束前,下一次调用将进入一个FIFO的等待队列,等待本次代码块执行结束,使用较为安全,若不考虑线程安全可使用DISPATCH_BLOCK_DETACHED,其它flag自行查阅文档。

    2.dispatch_block_perform 没有实际使用过,可能是在当前线程中将闭包的执行体放在指定的flag环境中去执行(待认证).

    3.dispatch_block_cancel 取消执行某个block,只有当block还未执行前执行cancel有效,block正在执行无法取消.
    4.dispatch_block_wait 等待block执行,直到timeout后继续往下执行代码,如果timeout=DISPATCH_TIME_FOREVER且block永远不被执行,代码将永远等待。
    5.dispatch_block_notify(block1,queue,notification_block);注册一个block1的监听,当block1已经完成的时候,会在queue里立即执行notification_block.


    简要Demo:

    • Demo1.简单用法
    dispatch_block_t _dblock;
    void testDispatchBlock() {
        
        while (_index < 10) {
            
            createBlockIfNeeded();
            executingBlockOrCancel();
        }
    }
    
    NSInteger _index;
    void createBlockIfNeeded() {
        
        if (!_dblock) {
            
            _dblock = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
                
                NSLog(@"index -> %lu",_index);
            });
        }
    }
    
    void executingBlockOrCancel() {
        
        if ( ++ _index % 2 ) {
            
            _dblock();
        }else {
            
            dispatch_block_cancel(_dblock);
            _dblock = nil;
        }
    }
    

    输出结果:

    2017-02-26 23:15:32.362374 dispatch_block_oc[60994:11193423] index -> 1
    2017-02-26 23:15:32.362444 dispatch_block_oc[60994:11193423] index -> 3
    2017-02-26 23:15:32.362471 dispatch_block_oc[60994:11193423] index -> 5
    2017-02-26 23:15:32.362491 dispatch_block_oc[60994:11193423] index -> 7
    2017-02-26 23:15:32.362511 dispatch_block_oc[60994:11193423] index -> 9
    
    • Demo2.当block在延时函数中使用
    void delayExecutingTask() {
        
        createBlockIfNeeded();
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), _dblock);
        //sometimes ,you need cancel the block,use dispatch_block_cancel 
        dispatch_block_cancel(_dblock);
    }
    
    • Demo3.dispatch_block_waite
    dispatch_block_t _dblock;
    void testDispatchBlock() {
        
        createBlockIfNeeded();
        executingBlockOrCancel();
    }
    
    NSInteger _index;
    void createBlockIfNeeded() {
        
        if (!_dblock) {
            
            _dblock = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
                
                [NSThread sleepForTimeInterval:5];
                NSLog(@"index -> %lu",_index);
            });
            
            NSLog(@"wait BEGIN ");
            dispatch_block_wait(_dblock, dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC));
            NSLog(@"wait END ");
        }
    }
    
    void executingBlockOrCancel() {
        
        if ( ++ _index % 2 ) {
            
            _dblock();
        }else {
            
            dispatch_block_cancel(_dblock);
            _dblock = nil;
        }
    }
    

    输出结果:

    2017-02-26 23:27:27.484894 dispatch_block_oc[61126:11221388] wait BEGIN 
    2017-02-26 23:27:29.485858 dispatch_block_oc[61126:11221388] wait END 
    2017-02-26 23:27:34.487206 dispatch_block_oc[61126:11221388] index -> 1
    

    demo中,在函数createBlockIfNeeded函数中,输出waite BEGIN之后,dispatch_block_waite函数将等待两秒,再输出waite END,之后才执行函数executingBlockOrCancel();

    • Demo4.dispatch_block_notify
    dispatch_block_t _dblock;
    void testDispatchBlock() {
        
        NSLog(@"BEGIN");
        createBlockIfNeeded();
        _dblock();
    }
    
    NSInteger _index;
    void createBlockIfNeeded() {
        
        if (!_dblock) {
            
            _dblock = dispatch_block_create(DISPATCH_BLOCK_BARRIER, ^{
                
                [NSThread sleepForTimeInterval:5];
                NSLog(@"index -> %lu",_index);
            });
            
            dispatch_block_notify(_dblock, dispatch_get_main_queue(), ^{
                
                NSLog(@"BLOCK EXECUT COMPLETED");
            });
        }
    }
    
    void executingBlockOrCancel() {
        
        if ( ++ _index % 2 ) {
            
            _dblock();
        }else {
            
            dispatch_block_cancel(_dblock);
            _dblock = nil;
        }
    }
    

    输出结果:

    2017-02-26 23:36:30.105075 dispatch_block_oc[61245:11242889] BEGIN
    2017-02-26 23:36:35.106363 dispatch_block_oc[61245:11242889] index -> 0
    2017-02-26 23:36:35.122696 dispatch_block_oc[61245:11242889] BLOCK EXECUT COMPLETED
    

    博主已经开通了博客地址: kobeluo,哪里有更丰富的资源,欢迎与我交流。

  • 相关阅读:
    第1章 引论
    Java反射
    用户职责菜单请求组
    API及接口清单
    独立值集导入脚本
    报表对应程序包查询
    正则表达式
    合并工作表
    去重
    分割表
  • 原文地址:https://www.cnblogs.com/KobeLuo/p/6464233.html
Copyright © 2020-2023  润新知