iOS底層原理篇 十七 Block初探

2021-10-08 22:09:58 字數 3452 閱讀 1807

1.block的分類

常見的三種block

-

(void

)viewdidload

;block()

;nslog

(@"%@"

,block);}

//列印結果

//block探析[2300:140310] 我是全域性block

//block探析[2300:140310] <__nsglobalblock__: 0x10d14e038>

-

(void

)viewdidload

;block()

;nslog

(@"%@"

,block);}

//列印結果:

//block探析[2416:146513] 我是全域性block---10

//block探析[2416:146513] <__nsmallocblock__: 0x600003db08d0>

-

(void

)viewdidload );

}//列印結果:

//block探析[2460:149166] <__nsglobalblock__: 0x109b7b038>

2.block捕獲外部變數

1.無__block修飾的區域性變數

#include

intmain()

;block()

;return0;

}//clang生成.cpp檔案

//下面是cpp檔案中main函式的實現**

intmain()

//這裡將我們block**塊裡面的**給了函式__main_block_func_0

//__main_block_impl_0:建構函式,返回值為乙個block!

//block的本質:結構體

struct __main_block_impl_0

}; */

void

(*block)

(void)=

((void(*

)())

&__main_block_impl_0((

void

*)__main_block_func_0,

&__main_block_desc_0_data, a));

/** //block結構體中的impl結構

struct __block_impl ;

//去掉強轉的**,這裡不就是block的呼叫:

block->funcptr(block);

*/((

void(*

)(__block_impl *))

((__block_impl *

)block)

->funcptr)

((__block_impl *

)block)

;return0;

}

2.__block修飾的區域性變數
#include

intmain()

;block()

;return0;

}//clang生成.cpp檔案

//下面是cpp檔案中main函式的實現**

intmain()

; */

__attribute__((

__blocks__

(byref)

)) __block_byref_a_0 a =;//

/** 這裡block初始化的時候,傳進來的是__block_byref_a_0結構體型別的指標a;

struct __main_block_impl_0

};*/

void

(*block)

(void)=

((void(*

)())

&__main_block_impl_0((

void

*)__main_block_func_0,

&__main_block_desc_0_data,

(__block_byref_a_0 *

)&a,

570425344))

;//呼叫

/** static void __main_block_func_0(struct __main_block_impl_0 *__cself)

*/((

void(*

)(__block_impl *))

((__block_impl *

)block)

->funcptr)

((__block_impl *

)block)

;return0;

}

3.block迴圈引用
-

(void

)viewdidload

;self

.block()

;}//這樣一段**,不用說,都知道會發生迴圈應用

//這是因為self->block->self形成了乙個閉環,並且都是強持有!

//所以這裡vc和block都無法釋放

//也就是說,只要打破這個迴圈,不會迴圈應用了!

//我們平時最多的使用是

//定義乙個弱引用weakself,指標指向self,因為是weak修飾,所以不對引用計數做任何操作

//__weak typeof(self) weakself = self;只需將self.name改為weakself.name就可打破迴圈

//這裡使用了中介者設計模式

//weakself(弱引用表)->self->block->weakself

//看需求及邏輯需要,只有這一句**有可能會有問題,

//比如把上面**改為:-(

void

)viewdidload );

};self

.block()

;}-(

void

)dealloc

//列印結果就是:

//block探析[3895:288440] 釋放了

//block探析[3895:288440] 我是---(null)

//列印的時候,vc已經釋放,屬性name肯定也被釋放了

//如果遇到這種情況,我們還需要做一步操作:

//__strong typeof(weakself) strongself = weakself;

改為strongself.name

//strongself臨時變數出了作用域會被釋放

//strongself->weakself(弱引用表)->self->block->weakself->strongself

//延遲釋放vc

//block探析[3922:291133] 我是---ios

//block探析[3922:291133] 釋放了

iOS 底層原理之 Block

block 本質上也是乙個 oc 物件,它內部也有個 isa 指標 block 是封裝了函式呼叫以及函式呼叫環境的 oc 物件 block 的底層結構如下圖所示 原始碼解析 struct gsblock load block impl 0 block impl struct block impl g...

iOS知識原理篇

weak策略表明該屬性定義了一種 非擁有關係 nonowning relationship 為這種屬性設定新值時,設定方法既不保留新值,也不釋放舊值。此特質同assign類似 然而在屬性所指的物件遭到摧毀時,屬性值也會清空 nil out runtime對註冊的類,會進行布局,會將 weak 物件放...

block的底層實現原理

block就是指向結構體的指標,編譯器會將block的內部 生成對應的函式,利用這個指標就可以呼叫這個函式.普通的區域性變數是值傳遞,用 block static 或者是全域性變數就是位址傳遞 block的記憶體預設是存放在棧裡面的,他不會對所引用的物件進行操作 如果對block做一次copy操作b...