Block詳細學習

2021-09-25 17:15:49 字數 4171 閱讀 6748

之前對block一知半解,知道用__block,__weak等去解決問題,卻沒有去深究過,這篇文章是對學習block的總結

要看block轉換為c++原始碼,用下面的方法轉換:

cd到.m所在資料夾, 輸入clang -rewrite-objc ***.m,就會在當前資料夾內自動生成對應的***.cpp檔案,雙擊開啟即可

看下oc轉換成c++的**

oc

typedef int(^block_t)(int);

- (void)testfunc ;

block(2);

}

c++

struct __block_impl ;

typedef int(*block_t)(int);

// @implementation testobj

**//block結構體**

struct __testobj__testfunc_block_impl_0

};**//block所呼叫的方法**

static int __testobj__testfunc_block_func_0(struct __testobj__testfunc_block_impl_0 *__cself, int count)

**//block附加資訊**

static struct __testobj__testfunc_block_desc_0 __testobj__testfunc_block_desc_0_data = ;

//**testfunc**

static void _i_testobj_testfunc(testobj * self, sel _cmd)

這麼一坨**,看起來就眼暈,多看幾遍就好了,最好是自己動手寫一下,然後轉換成c++,可以看出來block其實就是objective-c用來實現閉包的物件形式

1、全域性變數

2、全域性靜態變數

3、區域性靜態變數

4、區域性變數

oc

typedef int(^block_t)(int);

int global_val = 1;//全域性變數

static int static_global_val = 2;//全域性靜態變數

- (void)testfunc ;

block(2);

printf("---%d---%d---%d",global_val,static_global_val,static_val);

}

c++

struct __testobj__testfunc_block_impl_0 

};static int __testobj__testfunc_block_func_0(struct __testobj__testfunc_block_impl_0 *__cself, int count)

可以看到全域性變數和全域性靜態變數,block內部沒有做操作;區域性靜態變數時,將指標傳遞到block的建構函式(// bound by copy注釋是編譯器自動新增的),區域性變數不可做賦值操作;注意:如果區域性變數是nsmutablearray 型別時,在block內部做addobject操作是允許的,但是不可為區域性變數重新賦值;

對於block,我們會遇到在外部修改區域性的值以後,再次呼叫block時,裡面的區域性變數的值仍然和之前是一樣的情況。。下面來看下如果只是呼叫區域性變數的話block的內部操作

oc

typedef int(^block_t)(int);

- (void)testfunc ;

block(2);

}

c++

struct __testobj__testfunc_block_impl_0 

};static int __testobj__testfunc_block_func_0(struct __testobj__testfunc_block_impl_0 *__cself, int count)

可以看到,block中使用的區域性變數fmt,val被新增到了結構體中,沒有使用的則未新增。。函式體的**中,使用時取得是__cself中即結構體中的fmt和val,這兩個變數是值傳遞的,並沒有傳遞指標。。看來這就是外部變數的值改變時block內部值不變的原因了,也正是這個原因,block內部給外部的區域性變數賦值時會報錯。怎麼樣在block內部修改外部的值?怎麼讓區域性變數在block內外保持同步?就是__block

看下**

oc

- (void)testfunc ;

block();//20 20

a -= 20;

b += 30;

printf("%d, %d\n",a,b);//0 50

block(); //10 20

}

c++

struct __block_byref_a_0 ;

struct __testobj__testfunc_block_impl_0

};static void __testobj__testfunc_block_func_0(struct __testobj__testfunc_block_impl_0 *__cself)

static void __testobj__testfunc_block_copy_0(struct __testobj__testfunc_block_impl_0*dst, struct __testobj__testfunc_block_impl_0*src)

static void __testobj__testfunc_block_dispose_0(struct __testobj__testfunc_block_impl_0*src)

static struct __testobj__testfunc_block_desc_0 __testobj__testfunc_block_desc_0_data = ;

static void _i_testobj_testfunc(testobj * self, sel _cmd) ;

int b = 20;

block_t block = ((void (*)())&__testobj__testfunc_block_impl_0((void *)__testobj__testfunc_block_func_0, &__testobj__testfunc_block_desc_0_data, b, (__block_byref_a_0 *)&a, 570425344));

((void (*)(__block_impl *))((__block_impl *)block)->funcptr)((__block_impl *)block);

(a.__forwarding->a) -= 20;

b += 30;

printf("%d, %d\n",(a.__forwarding->a),b);

((void (*)(__block_impl *))((__block_impl *)block)->funcptr)((__block_impl *)block);

}

可以看到,被__block修飾後多了 __block_byref_a_0 這麼個結構體,在 __testobj__testfunc_block_impl_0 中 b 被表示為 int b,而加了__block的a則 表示為 __block_byref_a_0 *a; // by ref;下面就是

__block_byref_a_0

struct __block_byref_a_0 ;
在 _i_testobj_testfunc即testfun的方法中有a的宣告:attribute((blocks(byref))) __block_byref_a_0 a = ;

可以看到__forwarding是指向自身的,在__testobj__testfunc_block_impl_0中可以看到a(_a->__forwarding);即block的a是取的__forwarding;在block內和block外呼叫a的時候都用了a->__forwarding->a;這裡應該就是__block修飾符為什麼可以使block內部去修改block外部變數的關鍵

本文參考

ios底層原理總結 - 探尋block的本質

《objective-c-高階程式設計》乾貨三部曲(二):blocks篇

Block 學習筆記

一 什麼是block?a block is an anonymous inline collectionof code,and sometimes also called a closure 閉包是一種函式,它能夠讀取其它函式的內部變數。block 也相當於內聯函式,執行速度快,簡單方便 二 為什麼...

學習日記 block

block概念 1.內聯函式從源 層看,有函式的結構,而在編譯後,卻不具備函式的性質,編譯時,類似巨集替換,使用函式體替換呼叫處的函式名 2.block封裝了一段 可以在任何時候執行 3.block可以作為函式引數或者函式的返回值,而其本身又可以帶輸入引數或返回值 用途 在多執行緒 非同步任務 集合...

Objective C學習筆記 block

一 基本概念 1 block的作用 block封裝了一段 在任何時候都可以使用。block的標誌是 2 block的特點 block可以作為函式引數或者函式的返回值,而其本身又可以帶輸入引數或返回值,和函式很像。二 基本使用 1 定義block變數 1 無形參 無返回值 void myblock 定...