在通讀文章之前,您可能需要瞭解記憶體配置的基礎知識。
預設情況下,block是存檔在棧中,可能被隨時回收,通過copy操作可以使其在堆中保留一份, 相當於一直強引用著, 因此如果block中用到self時, 需要將其弱化, 通過__weak或者__unsafe_unretained. 以下是範例程式碼及其說明, 讀者可以試著列印出不同情況下block的記憶體情況
當函數內部代碼結束時,函數中的所有儲存在棧區的變數都會被系統釋放, 因此如果屬性的block是用assign修飾時 當再次訪問時就會出現野指標訪問.
[objc] view plain copy #import "ViewController.h" @interface ViewController () @property (nonatomic, copy) void(^myblock)(); @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //1 __NSGlobalBlock__ 全域block 儲存在代碼區(儲存方法或者函數) void(^myBlock1)() = ^() { NSLog(@"我是老大"); }; NSLog(@"%@",myBlock1); //2 __NSStackBlock__ 棧block 儲存在棧區 //block內部訪問外部變數 //block的本質是一個結構體 int n = 5; void(^myBlock2)() = ^() { NSLog(@"我是老二%d", n); }; NSLog(@"%@", myBlock2); //3 __NSMallocBlock__ 堆block 儲存在堆區 對棧block做一次copy操作 void(^myBlock3)() = ^() { NSLog(@"我是老二%d", n); }; NSLog(@"%@", [myBlock3 copy]); /* 由以上三個例子可以看出當block沒有訪問外界的變數時,是儲存在代碼區, 當block訪問外界變數時時儲存在棧區, 而此時的block出了範圍就會被釋放 以下樣本: */ [self test];//當此代碼結束時,test函數中的所有儲存在棧區的變數都會被系統釋放, 因此如果屬性的block是用assign修飾時 當再次訪問時就會出現野指標訪問. self.myblock(); } - (void)test { int n = 5; [self setMyblock:^{ NSLog(@"%d",n); }]; &nbs