標籤:
1 關於__block變數為什麼可以在block體內修改值
1234567891011121314 |
void foo() { __block int i = 1024 ; //此時i在棧上 int j = 1 ; //此時j在棧上 void (^blk)( void ); blk = ^{printf( "%d, %d\n" , i, j); }; //此時,blk已經初始化,它會拷貝沒有__block標記的常規變數自己所持有的一塊記憶體區,這塊記憶體區現在位於棧上,而對於具有__block標記的變數,其地址會被拷貝置前述的記憶體區中 blk(); //1024, 1 void (^blkInHeap)( void ) = Block_copy(blk); //複製block後,block所持有的記憶體區會被拷貝至堆上,此時,我們可以說,這個block現在位於堆上 blkInHeap(); //1024,1 i++; j++; blk(); //1025,1 blkInHeap(); //1025,1 } |
讓我們一步步剖析:
首先,我們在棧上建立了變數ij,並賦予初始值,然後建立一個block變數名為blk,但未賦值。
然後我們初始化這個blk,賦值為一個只有一句printf的block,值得注意的是,一個block一旦建立,其引用到的常規變數會進行如下操作:
沒有__block標記的變數,其值會被複製一份到block私人記憶體區
有__block標記的變數,其地址會被記錄在block私人記憶體區
然後調用blk,列印1024, 1很好理解
接下來複製blk到堆,名曰blkInHeap,調用之,列印1024, 1也很好理解
接下來我們為ij增值,使其變為1025和2,此時再調用blk或者blkInHeap,會發現結果為1025, 1,這是因為變數j早已在建立原始的block時,被賦值進block的私人記憶體區,後續對i的操作並非操作的私人記憶體區的複製品,當調用blk或者blkInHeap時,其列印使用的是私人記憶體區的複製品,故而列印結果依舊為1;而變數j的修改會即時生效,因為block記錄的是它的地址,通過地址來訪問其值,使得外部對j的修改在block中得以生效。
2 關於使用
轉載自:http://fuckingblocksyntax.com/
How Do I Declare A Block in Objective-C?
As a
local variable:
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
As a
property:
@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
As a
method parameter:
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
As an
argument to a method call:
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
As a
typedef:
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
Objective-C block