對iOS中block的一點領悟

2021-06-21 05:19:59 字數 2194 閱讀 4097

看之前可以先做一下這個測試題目

,如果都不能難倒你,那麼下面的你也不用看了。

在objective-c語言中,一共有3種型別的block:

_nsconcreteglobalblock 全域性的靜態block,不會訪問任何外部變數。

_nsconcretestackblock 儲存在棧中的block,當函式返回時會被銷毀。

_nsconcretemallocblock 儲存在堆中的block,當引用計數為0時會被銷毀。

一、全域性靜態的block和c函式是一樣的,位於**段中,其特徵就是麼有引用任何外部變數

;

nslog(@"block is %@", sum); //block is <__nsglobalblock__: 0x47d0>

}

二、儲存在棧中的block,block函式返回時被銷毀,其引用的外部變數會被copy到棧上去,所以在這一型別block中引用了外部變數是無法改變外部變數的,當然我們可以使用__block來修飾你想要改變的外部變數以告知編譯器「我需要在block內部修改這個外部變數」,這樣編譯器就會在block內部直接使用該變數的引用而不是再copy乙份。

;

nslog(@"block is %@", ^);

//block is <__nsstackblock__: 0xbfffdac0>

//列印可看出block是乙個 nsstackblock, 即在棧上, 當函式返回時block將無效

nslog(@"block is %@", testblock);

//block is <__nsmallocblock__: 0x75425a0>

//上面這句在非arc中列印是 nsstackblock, 但是在arc中就是nsmallocblock

//即在arc中缺省會將block從棧複製到堆上,而在非arc中,則需要手動copy.

}

此外儲存在棧中的block對於arc和非arc來說有一點的區別,arc中缺省會將棧中的block拷貝到堆中來(其原因本也不是很清楚,但是從下面提到的一些參考資料中很可能是因為arc中預設是strong的引用型別,那麼將預設把block拷貝到堆上由arc來管理其記憶體),來看下面乙個例子:

void exampleb_addblocktoarray(nsmutablearray *array) ];} 

void exampleb()

由於該block引用了外面變數「b」,所以這個block的應該是儲存在棧上的。在來看看它在arc和非arc中區別:

首先在非arc中,它是乙個棧block所以它會在函式返回是銷毀,那麼在addobject的時候,此block已經被銷毀了;

在arc中,它會預設被copy到堆中來成為乙個堆block,函式返回不會立即被銷毀,將由arc來管理其記憶體,所以以上**是正確可行的。

三、儲存在堆的block,我們可以通過copy棧block來得到堆block,c系列的程式設計師應該都知道堆上的記憶體是由我們自己管理的,所以在非arc中需要自己管理其記憶體,而在arc中我們只需要交給arc去管理就好了。

此外使用block有一點是需要特別注意的就是防止迴圈引用:

@property (nonatomic, copy)testblock block;

self.block = ^;

self.block();

如上:self持有myblock,在block中又引用了self,block在被copy到堆上的時候會retain其引用的外部變數,這樣myblock也持有了self,他們相互持有就造成了迴圈引用,誰都無法釋放。

arc中正確的做法是:

__weak testbviewcontroller* weakself = self;

self.block = ^;

self.block();

非arc中正確的做法是:

self.block = ^;

self.block();

self.block = nil;

當然在arc中也可以加上「self.block = nil」這句來達到釋放block的目的,但是這樣的做法是不推薦的。

以上領悟主要參考了一下blog

唐巧boy的blog(知名ios開發大牛)

對block的一點理解

對block的理解 block宣告的寫法 property strong,nonatomic void block void property copy,nonatomic void block void block的本質 就是oc的物件,內部也有isa指標,block是封裝了函式呼叫以及函式呼叫環...

關於位址運算的一點領悟

資料結構課上,老師講到如何得到乙個指標的位址的時候,說到了l i sizeof elemtype 和l i,課上老師說改用前者。我回到宿舍用vs2013實驗了一下,如下 includeusing namespace std void main int p m cout m 1 m 1 endl co...

關於單例設計的一點小領悟

今天學習了很多其中單例設計 有一點沒理解 後面問了同學才明白了 下面再說我遇到的那個傻瓜般的問題 單例設計 意思就是配置檔案 只需要乙個配置檔案就可以了 想要保證唯一性?1.為了避免其他程式過多建立該類物件,先禁止其他程式建立該類物件 2.為了讓其他程式可以訪問到該類物件,只好在本類中,自定義乙個物...