Block有三種類型:
- __NSGlobalBlock
- __NSStackBlock
- __NSMallocBlock
我們?cè)谥vblock的本質(zhì)的時(shí)候已經(jīng)知道了,block的本質(zhì)就是一個(gè) OC 對(duì)象,那么既然它是一個(gè) OC 對(duì)象,它就會(huì)有類型,本文就將講解block
的三種類型.并都繼承于NSBlock
我們?cè)谥vblock
的三種類型之前,先了解一下程序的內(nèi)存分配情況,因?yàn)椴煌愋偷?code>block分配的內(nèi)存也不同.
.text段 : 也稱代碼段,我們寫(xiě)的代碼都存放在這里
.data區(qū) : 也稱數(shù)據(jù)區(qū),一般存放全局變量, __NSGlobalBlock存放在這里
堆區(qū) : 存放我們自己
alloc
出來(lái)的對(duì)象,動(dòng)態(tài)分配內(nèi)存,需要程序員自己申請(qǐng)內(nèi)存,自己管理. __NSMallocBlock存放在堆區(qū)-
棧區(qū) : 一般存放局部變量,不需要程序員管理,系統(tǒng)自動(dòng)分配,自動(dòng)銷毀,__NSStackBlock存放在棧區(qū)
不同block類型的內(nèi)存分配
一: __NSGlobalBlock
結(jié)論: 沒(méi)有訪問(wèn) auto變量 的block 就是 __NSGlobalBlock
int main(int argc, const char * argv[]) {
@autoreleasepool {
static int age = 10;
void(^block)(void) = ^{
NSLog(@"Hello, World! %d",age);
};
NSLog(@"%@",[block class]);
}
return 0;
}
控制臺(tái)輸出:__NSGlobalBlock__
二: __NSStackBlock
結(jié)論:訪問(wèn)了auto變量 的block 就是 __NSStackBlock
int main(int argc, const char * argv[]) {
@autoreleasepool {
int age = 10;
void(^block)(void) = ^{
NSLog(@"Hello, World! %d",age);
};
NSLog(@"%@",[block class]);
}
return 0;
}
控制臺(tái)輸出:__NSMallocBlock__
怎么打印的是NSMallocBlock,剛才不是說(shuō)訪問(wèn)了auto變量就是__NSStackBlock嗎?
因?yàn)檫@里我們使用的是ARC,在ARC環(huán)境下,Xcode編譯器再某些情況會(huì)默認(rèn)幫我們做調(diào)用copy 變成堆block ,我們?cè)贐uild Settings中把ARC設(shè)置成MRC,再來(lái)打印一下:
2018-08-30 17:37:09.846365+0800 block的類型[4318:3463149] __NSStackBlock__
這次打印的就是NSStackBlock
我們思考一下,__NSStackBlock在訪問(wèn)外部變量時(shí),會(huì)有什么問(wèn)題?
會(huì)出現(xiàn)野指針crash 所以在ARC壞境Xcode幫我們處理成了堆block(NSMallocBlock)防止出現(xiàn)釋放了還去訪問(wèn)導(dǎo)致野指針crash
三: __NSMallocBlock
結(jié)論: 當(dāng)一個(gè)__NSStackBlock調(diào)用了copy操作,返回的就是一個(gè)__NSMallocBlock
??注意
以上都是在MRC環(huán)境下
如果是在ARC環(huán)境下,編譯器會(huì)根據(jù)情況自動(dòng)將棧上的block復(fù)制到堆上, 比如以下幾種情況:
-
- block作為函數(shù)返回值時(shí)
block作為返回值編譯器會(huì)自動(dòng)copy
image -
2.將block賦值給__strong指針時(shí)
被強(qiáng)指針引用的block會(huì)自動(dòng)copy
image -
3.block作為Cocoa API方法名含有UsingBlock的方法參數(shù)時(shí)
UsingBlock
image -
4.block作為GCD API的方法參數(shù)時(shí)
GCD API的方法參數(shù)
- 5.block調(diào)用copy方法
總結(jié):
1:一共有三種類型的Block.分為_(kāi)_NSGlobalBlock,__NSStackBlock,__NSMallocBlock.
沒(méi)有訪問(wèn) auto變量 的block 就是 __NSGlobalBlock
訪問(wèn)了auto變量 的block 就是 __NSStackBlock
當(dāng)一個(gè)__NSStackBlock調(diào)用了copy操作,返回的就是一個(gè)__NSMallocBlocksing
2:在ARC環(huán)境下,編譯器會(huì)自動(dòng)把棧上的block copy到堆上