block的結(jié)構(gòu)
return_type (^block_name)(paratemters)
block的基本用法
int additional = 5;
int (^addBlock)(int a, int b) = ^(int a, int b){
return a + b+ addition;
}
默認(rèn)情況下夺衍,為block所捕獲的變量狈谊,是不可以在塊里修改的(需要加__block)
NSArray *array = @[@0, @1, @2, @3, @4, @5];
__block int count = 0;
[array enumerateObjectsUsingBlock:^(NSNumber *number, NSUInteger idx, BOOL *stop) {
if ([number compare:@2] == NSOrderedAscending) {
count ++;
}
}];
// count = 2;
塊總能修改實例變量,所以在聲明時無需加__block
在定義blcok的時候沟沙,所占內(nèi)存分配的棧中的河劝,這就是說,塊只在定義他的那個范圍內(nèi)有效
一下代碼就很危險
void (^block)();
if (count == 2) {
block = ^{
NSLog(@"Block A");
};
}else{
block = ^{
NSLog(@"Block B");
}
block();
首先棧內(nèi)存是分配是有編譯器分配和釋放的矛紫,以上代碼中if和else中的block被分配到棧內(nèi)存中(這兩個塊只能保證在對應(yīng)的if或else語句范圍內(nèi)有效)赎瞎,如果編譯器把分配給block的內(nèi)存給覆寫掉,那么程序就會崩潰颊咬。
注意:對于棧來講务甥,是由編譯器自動管理,無需我們手工控制喳篇;對于堆來講敞临,釋放工作有程序員控制,容易產(chǎn)生memory Leak麸澜。
為解決以上問題挺尿,我們可以給block對象發(fā)送copy消息,把block從棧復(fù)制到堆上。
void (^block)();
if (count == 2) {
[block = ^{
NSLog(@"Block A");
} copy];
}else{
[block =^{
NSLog(@"Block B");
} copy];
}
block();
全局塊
可以把塊定義為全局變量编矾,在文件級別上使用熟史。全局塊可以聲明到全局內(nèi)存中,而不需要在每次用到得時候于棧中創(chuàng)建窄俏。另外全局塊的copy是個空操作以故,因為全局塊絕不可能為系統(tǒng)所回收。
block一般有三種裆操,NSConcreteGlobal, NSConcreteStack, NSConcreteMalloc怒详。
block是可以訪問block外部的變量的。
NSConcreteGlobal: 就像一個全局函數(shù)一樣踪区,從頭到尾待在那昆烁,始終是可用的。當(dāng)Block中沒有引用外部變量時缎岗,block為global類型的静尼。
NSConcreteStack: 保存在棧中的block,block執(zhí)行完后內(nèi)存會被釋放掉传泊。當(dāng)block引用了外部變量時鼠渺,block為stack類型的。
NSConcreteMallock: 保存在堆中的block眷细,block為引用記數(shù)為0時拦盹,內(nèi)存會被釋放掉。當(dāng)block執(zhí)行copy時溪椎,block會從棧中復(fù)制到堆中普舆。
以上都針對非ARC環(huán)境而言,如果在ARC環(huán)境下校读,引用外部變量的block會自動保存在堆中沼侣,無需copy。
待續(xù)歉秫。蛾洛。。
block的理解http://answerhuang.duapp.com/index.php/2013/09/07/objective-c-blocks-syntax/#carousel-generic-38