1.block 用到的局部變數是 唯讀,將關鍵字__block 定義局部變數 則變為可讀寫。
2.如果局部變數類型是 基礎資料型別 (Elementary Data Type),比如NSinteger,那麼block使用局部變數其實是其拷貝,類似於函數參數傳值方式,所以在定義block之後修改局部變數對block代碼塊的內容沒有影響。
NSInteger outNum11 = 10; NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>%p %d",&outNum11,outNum11); return outNum11+a;};outNum11 =5;NSLog(@">>>&outnum11=%p %d",&outNum11,outNum11);NSLog(@">>>%d ",blockOne11(3));
輸出結果,是13而不是8,從outNum11的地址指標也可以看出兩者已經不同。
2012-09-02 11:33:51.606 TestBlockExample[984:f803] >>>&outnum11=0xbfffdcf4 5
2012-09-02 11:33:51.608 TestBlockExample[984:f803] >>>0xbfffdcec 10
2012-09-02 11:33:51.610 TestBlockExample[984:f803] >>>13
3.如果局部變數類型是 NSobject類型,那麼block使用局部變數,仍按函數參數傳值方式,只是此時局部變數類型為指標,其值為指標所指對象地址,所以指標按值拷貝後仍指向相同的對象地址。
NSMutableArray* outArray = [NSMutableArray arrayWithObjects:@"one",@"two",@"three", nil];NSMutableArray* (^blockOne)(NSMutableArray*) = ^(NSMutableArray* array){NSLog(@"\n>>>block %p %p %@",&outArray,outArray,outArray);[array removeLastObject]; return array;};[outArray removeObjectAtIndex:0];NSLog(@"\n>>>main %p %p %@",&outArray,outArray,outArray);NSLog(@"\n>>>result%@ %p %p %@",blockOne(outArray),&outArray,outArray,outArray);
輸出結果
2012-09-02 11:40:13.213 TestBlockExample[1072:f803] >>>main 0xbfffdcd4 0x6a2d4f0 ( two, three)2012-09-02 11:40:13.213 TestBlockExample[1072:f803] >>>block 0xbfffdccc 0x6a2d4f0 ( two, three)2012-09-02 11:40:13.214 TestBlockExample[1072:f803] >>>result( two) 0xbfffdcd4 0x6a2d4f0 ( two)
4.若局部變數加上__block,則block內局部變數變為可讀寫,其實這時是類似於將原來使用的局部變數 按傳值方式改為 傳地址方式。
__block NSInteger outNum11 = 10; NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>block %p %d",&outNum11,outNum11); return outNum11+a;};outNum11 =5;NSLog(@">>>main =%p %d",&outNum11,outNum11);NSLog(@">>>%d ",blockOne11(3));
輸出結果,可以看到此時block中的局部變數地址沒變
2012-09-02 11:49:08.557 TestBlockExample[1108:f803] >>>&outnum11=0xbfffdcf8 52012-09-02 11:49:08.559 TestBlockExample[1108:f803] >>>0xbfffdcf8 52012-09-02 11:49:08.560 TestBlockExample[1108:f803] >>>8
局部變數為NSobject對象時
__block NSMutableArray* outArray = [NSMutableArray arrayWithObjects:@"one",@"two",@"three", nil];NSMutableArray* (^blockOne)(NSMutableArray*) = ^(NSMutableArray* array){NSLog(@"\n>>>block %p %p %@",&outArray,outArray,outArray);[array removeLastObject]; return array;};[outArray removeObjectAtIndex:0];NSLog(@"\n>>>main %p %p %@",&outArray,outArray,outArray);NSLog(@"\n>>>result%@ %p %p %@",blockOne(outArray),&outArray,outArray,outArray);
輸出結果,
2012-09-02 11:55:43.666 TestBlockExample[1197:f803] >>>main 0xbfffdcf0 0x68b69e0 ( two, three)2012-09-02 11:55:43.666 TestBlockExample[1197:f803] >>>block 0xbfffdcf0 0x68b69e0 ( two, three)2012-09-02 11:55:43.667 TestBlockExample[1197:f803] >>>result( two) 0xbfffdcf0 0x68b69e0 ( two)
5.如果局部變數為static,則直接可以讀寫的,原因一樣,因為是靜態,所以只有一份
static NSInteger outNum11 = 10; NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>block %p %d",&outNum11,outNum11); outNum11=7; return outNum11+a;};outNum11 =5;NSLog(@">>>main =%p %d",&outNum11,outNum11);NSLog(@">>>%d ",blockOne11(3));
輸出結果:
2012-09-02 11:55:43.663 TestBlockExample[1197:f803] >>>main =0x4730 52012-09-02 11:55:43.665 TestBlockExample[1197:f803] >>>block 0x4730 52012-09-02 11:55:43.666 TestBlockExample[1197:f803] >>>10
6.定義block 指標類似與 函數指標,可以作為 方法的參數
NSInteger (^blockOne11)(NSInteger) = ^(NSInteger a){NSLog(@">>>block %p %d",&outNum11,outNum11); outNum11=7; return outNum11+a;};
- (void)testBlock:(NSString*(^)(NSString*input))inputBlock{NSLog(@">>>result=%@", inputBlock(@"kkk"));}
7.block 也是繼承與NSobject,block一般分配與stack,所以退出對應程式塊時會自動釋放,所以通過方法返回block時需要 對block指標做copy 在返回。
block與NSobject對象不同是,不能向block對象發送訊息。
如果對block對象copy 則會自動對局部變數做retain(如果是NSObject),或拷貝到heap中(非NSobject對象)。另外,當局部變數使用了__block關鍵字,則不retain
8.如果block存取 類執行個體成員,不管通過存取器或直接存取成員,都會retain self 和該執行個體變數。