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,哪里有更豐富的資源,歡迎與我交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM