//Block語法
//^返回值類型(參數列表){表達式}
- (void)some{
? ? ^int(int count){
? ? ? ? return count + 1;
? ? };
? ? //返回值類型可省略
? ? ^(int count){
? ? ? ? return count + 1;
? ? };
? ? //參數列表為空,可省略
? ? ^{
? ? ? ? return @"123";
? ? };
? ? //最簡潔的語法:^{};
}
- (block)someActionTwo:(block)block{
? ? return^(inti){
? ? ? ? block(2);
? ? ? ? returni +1;
? ? };
}
blockblockt =? [selfsomeActionTwo:^int(inti) {
? ? ? ? NSLog(@"##########i");
? ? ? ? returni;
? ? }];
block的用法
1.block作為參數
[selfsomeAction:^int(inti) {
? ? ? ? NSLog(@"i");
? ? ? ? returni ++;
? ? }];
- (void)someAction:(int(^)(inti))block{
? ? block(2);
}
2.block作為屬性變量
//Block類型變量 語法:返回值類型(^變量名)(參數列表)
@property(nonatomic,copy)NSString *(^Block)(NSString *strone);
//借助typedef可簡寫typedef int(^block)(int);
block的分類
block分為棧block:_NSConcreteStackBlock,堆block:_NSConcreteMallocBlock,全局block:_NSConcreteGlobalBlock
棧block:block最初是在棧上創建的,只用到局部變量,沒有被強指針指向的block是棧block;
堆block:在ARC中,系統會視情況而定(一旦block被賦值就會被copy到堆上),將棧上的block,copy到堆上,這是因為棧上的內存是有系統控制的,棧block出了作用域就會被銷毀,為了延長block的生命周期,將其copy到堆上
全局block:生命周期從創建開始到程序結束,相當于單例的存在,它不會用到臨時變量,只會用到全局或靜態變量或者沒有用到變量
block對外界變量的捕獲
block可以捕獲任何外界變量,捕獲到之后會將其作為自身結構體的成員變量,其中局部變量,靜態變量會被追加到block結構體的構造函數中,從clang翻譯的源碼中可以看到:
void?(*Block)(void) = ((void?(*)())&__main_block_impl_0((void?*)__main_block_func_0, &__main_block_desc_0_DATA, &static_k, val));
block的構造函數追加了局部變量的值,和靜態變量的地址
?static int j = 10;
? ? inti =10;
? void(^block)(void) =? ^{
? ? ? ? NSLog(@"打印i:%dj:%d",i,j);
? ? };
? ? i++;
? ? j++;
? ? block();
打印結果為i:10,而不是11,因為block只捕獲了局部變量的值,沒有捕獲地址,block內部會用到什么,在它創建的時候就會去捕獲什么,這時候捕獲到的也只能是值,為了防止局部變量之后被銷毀,需要知道它的值的時候取不到了,所以是提前捕獲,后續改變量的值在怎么變化,block取的都是最初捕獲的值. ?j:11,因為j是靜態變量捕獲了它的地址,所以可以實時獲取j的值。
block內部修改外部變量
如果block內部直接修改外部變量,編譯器會提示我們要加上__block ,為什么需要加上__block就可以修改了呢?
1.block捕獲外界局部變量只是捕獲了它的值,并沒有捕獲它的地址,對它只有只讀能力,沒有寫的能力
2.被__block修飾之后,該變量會被轉換為一個結構體:
struct __Block_byref_i_0 {
? void *__isa;
__Block_byref_i_0 *__forwarding;
int __flags;
int __size;
int i;
};
結構體中,它里面包含了isa,forwarding指針,flag標示,size大小,變量值,名字和變量名同名,在block的構造函數中 我們可以看到,追加了forwarding指針,block可以通過forwarding指針訪問變量,進而操作變量。