iOS Block面試題(Block的幾種形式)

文章系列持續(xù)更新 點贊再看,感謝觀看,更多請關(guān)注!更多面試文章和答案請觀看“面試合集”

注意:文末有整理面試題和資料提供!

Block的幾種形式

分為全局Block(_NSConcreteGlobalBlock)、棧Block(_NSConcreteStackBlock)、堆Block(_NSConcreteMallocBlock)三種形式
其中棧Block存儲在棧(stack)區(qū),堆Block存儲在堆(heap)區(qū),全局Block存儲在已初始化數(shù)據(jù)(.data)區(qū)
1、不使用外部變量的block是全局block

比如:

NSLog(@"%@",[^{
    NSLog(@"globalBlock");
} class]);

輸出:

NSGlobalBlock
2、使用外部變量并且未進行copy操作的block是棧block

比如:

NSInteger num = 10;
NSLog(@"%@",[^{
NSLog(@"stackBlock:%zd",num);
} class]);
輸出:

NSStackBlock
日常開發(fā)常用于這種情況:

[self testWithBlock:^{
NSLog(@"%@",self);
}];

  • (void)testWithBlock:(dispatch_block_t)block {
    block();

    NSLog(@"%@",[block class]);
    }
    3、對棧block進行copy操作,就是堆block,而對全局block進行copy,仍是全局block

比如堆1中的全局進行copy操作,即賦值:
void (^globalBlock)(void) = ^{
NSLog(@"globalBlock");
};

NSLog(@"%@",[globalBlock class]);
輸出:

NSGlobalBlock
仍是全局block

而對2中的棧block進行賦值操作:
NSInteger num = 10;

void (^mallocBlock)(void) = ^{

    NSLog(@"stackBlock:%zd",num);
};

NSLog(@"%@",[mallocBlock class]);
輸出:

NSMallocBlock
對棧blockcopy之后,并不代表著棧block就消失了,左邊的mallock是堆block,右邊被copy的仍是棧block
比如:

[self testWithBlock:^{

NSLog(@"%@",self);

}];

  • (void)testWithBlock:(dispatch_block_t)block
    {
    block();

    dispatch_block_t tempBlock = block;

    NSLog(@"%@,%@",[block class],[tempBlock class]);
    }
    輸出:

NSStackBlock,NSMallocBlock
即如果對棧Block進行copy,將會copy到堆區(qū),對堆Block進行copy,將會增加引用計數(shù),對全局Block進行copy,因為是已經(jīng)初始化的,所以什么也不做。
另外,__block變量在copy時,由于__forwarding的存在,棧上的__forwarding指針會指向堆上的__forwarding變量,而堆上的__forwarding指針指向其自身,所以,如果對__block的修改,實際上是在修改堆上的__block變量。

即__forwarding指針存在的意義就是,無論在任何內(nèi)存位置,都可以順利地訪問同一個__block變量。

另外由于block捕獲的__block修飾的變量會去持有變量,那么如果用__block修飾self,且self持有block,并且block內(nèi)部使用到__block修飾的self時,就會造成多循環(huán)引用,即self持有block,block 持有__block變量,而__block變量持有self,造成內(nèi)存泄漏。
比如:
__block typeof(self) weakSelf = self;

_testBlock = ^{
    
    NSLog(@"%@",weakSelf);
};

_testBlock();

如果要解決這種循環(huán)引用,可以主動斷開__block變量對self的持有,即在block內(nèi)部使用完weakself后,將其置為nil,但這種方式有個問題,如果block一直不被調(diào)用,那么循環(huán)引用將一直存在。
所以,我們最好還是用__weak來修飾self

有一些面試進階資料,iOS底層視頻+BAT面試專題PDF資料+最新《大廠常問面試答案》。希望能夠幫助到大家提升技術(shù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容