Block使用中的一些疑問解答

2021-06-07 11:36:15 字數 2195 閱讀 9451

本文主要是闡述一下block中如何的使用外部變數以及block本身的記憶體管理。

先定義乙個block變數,作為後續的例子中使用:

typedef

void

(^blockcc

)(void

);blockcc

_block

;

block中可以直接使用外部的變數,比如

int

number =1

;_block

=^();

那麼實際上,在block生成的時候,是會把number當做是常量變數編碼到block當中。可以看到,以下的**,block中的number值是不會發生變化的:

int

number =1

;_block

=^();

number =2

;_block

();

則輸出的值為 1,而不是2。原因就是如上所說。

如果要在block中嘗試改變外部變數的值,則會報錯的。對於這個問題的解決辦法是引入__block識別符號。將需要在block內部修改的變數標識為__block scope。更改後的**如下:

__block 

intnumber =1

;_block

=^();

而這個時候,其實block外部的number和block內部的number指向了同乙個值,回到剛才的在外部改變block的例子,它的輸出結果將是2,而不是1。有興趣的可以自己寫乙個例子試試。

block本身是像物件一樣可以retain,和release。但是,block在建立的時候,它的記憶體是分配在棧(stack)上,而不是在堆(heap)上。他本身的作於域是屬於建立時候的作用域,一旦在建立時候的作用域外面呼叫block將導致程式崩潰。比如下面的例子。

我在view did load中建立了乙個block:

-

(void

)viewdidload

;}

並且在乙個按鈕的事件中呼叫了這個block:

-

(ibaction

)testdidclick

:(id

)sender

此時我按了按鈕之後就會導致程式崩潰,解決這個問題的方法就是在建立完block的時候需要呼叫copy的方法。copy會把block從棧上移動到堆上,那麼就可以在其他地方使用這個block了~

修改**如下:

_block 

=^();

_block =[

_blockcopy

];

同理,特別需要注意的地方就是在把block放到集合類當中去的時候,如果直接把生成的block放入到集合類中,是無法在其他地方使用block,必須要對block進行copy。不過**看上去相對奇怪一些:

[

array addobject

:[[^

copy

]autorelease

]];

這一點其實是在第一點的乙個小的衍生。當在block內部使用成員變數的時候,比如

@inte***ce

viewcontroller

:uiviewcontroller

@end

在block建立中:

_block 

=^();

這裡的_string相當於是self->_string;那麼block是會對內部的物件進行一次retain。也就是說,self會被retain一次。當self釋放的時候,需要block釋放後才會對self進行釋放,但是block的釋放又需要等self的dealloc中才會釋放。如此一來變形成了迴圈引用,導致記憶體洩露。

修改方案是新建乙個__block scope的區域性變數,並把self賦值給它,而在block內部則使用這個區域性變數來進行取值。因為__block標記的變數是不會被自動retain的。

__block 

viewcontroller

*controller

=self

;_block

=^();

先寫到這裡,基本是我在用block時候碰到的一些問題。需要更詳細的解釋,可以看看《adanced mac os x programming》這本書,推薦給大家。

Block使用中的一些疑問解答

本文主要是闡述一下block中如何的使用外部變數以及block本身的記憶體管理。先定義乙個block變數,作為後續的例子中使用 typedef void blockcc void blockcc block 1 block中引用外部變數 block中可以直接使用外部的變數,比如 int number...

spi一些疑問的解答

在spidev.c有read write 以及spidev message函式.分別實現半雙工和全雙工的功能.不過最後呼叫的都是spi控制器驅動的transfer函式.例如,atmel spi transfer drivers spi atmel spi.c 那麼驅動如何判斷應用程式要讀還是寫呢?簡...

關於HashMap的一些疑問與解答

1.為什麼treeify threshold要是8?treefy是有成本的,新增或刪除元素時有額外的操作,同時treenode是普通node體積的二倍,因而需要乙個平衡點。隨機hashcode下符合泊松分布,0 0.60653066 1 0.30326533 2 0.07581633 3 0.012...