iOS Blockの基本構文と使用


iOSではblockがよく使われていますが、OCの文法とはちょっと合わないので理解しにくいです.
以下は私個人の初歩的な理解で、調べるためです.
1.blockの声明
 //    block

typedef NSString *(^WXYTestBlock)(NSString *name, int age);

以上、WXYTestBlockという名前のblockを宣言しました.パラメータは文字列タイプのnameとintタイプのageで、戻り値はNSStringです.
もちろん、このように宣言することもできます.
typedef void (^WXYTestBlock)(void); 

パラメータなし、戻り値なし.
もちろん、パラメータに戻り値がない場合や、戻り値がある場合はパラメータがない場合もあり、一つ一つ列挙しない.
2.blockの使用
まずは独立ブロック
 //  block    

WXYTestBlock myBlock = ^ (NSString *name, int age){       

     return [NSString stringWithFormat:@"%@    %d",name,age];   

 };    

NSLog(@"  block--->%@", myBlock(@"  ", 16));

独立blockは直接定義して使用することができて、出力を実行します
2015-06-03 23:32:32.532 WXYBlock[3537:237755]   block--->      16 

そしてインラインブロック
//    block   

- (void)printWithName:(NSString *)name age:(int)age block:(WXYTestBlock)block{    NSLog(@"  block--->%@",block(name, age));

}

インラインblockは、定義されたblockをパラメータとして対応するメソッドに入力し、メソッドでblockを使用する必要があります.
 //  block   

 [self printWithName:@"   " age:26 block:^(NSString *str, int age){       

     return [NSString stringWithFormat:@"%@    %d", str, age];   

 }];

インラインブロックはメソッドを呼び出すときにコードブロックに書き込むことができ、実行結果は以下の通りです.
2015-06-03 23:32:32.532 WXYBlock[3537:237755]   block--->       26 

3.block外部変数の使用
//        

 int myAge = 100;    

//  block    

myBlock = ^ (NSString *name, int age){        

    return [NSString stringWithFormat:@"    --->%@    %d", name, myAge];   

 };    

NSLog(@"  block--->%@", myBlock(@"  ", 16));    

//  block   

 [self printWithName:@"   " age:26 block:^(NSString *str, int age){       

     return [NSString stringWithFormat:@"    --->%@    %d", str, myAge];  

 }]; 

block内部では外部定義の変数を直接使用でき、実行結果は以下の通りです.
#  :      ,   myAge      age,    16         。

2015-06-03 23:32:32.533 WXYBlock[3537:237755]   block--->    --->      1002015-06-03 

23:32:32.533 WXYBlock[3537:237755]   block--->    --->       100 

興味深い現象です
独立したblockを定義し、このblockは外部の変数を使用します.
そしてこの変数が変更され、あなたはこのblockを呼び出しました.
注意:
独立したblockを定義し、外部変数→外部変数を使用して変更→blockを呼び出す
//          

myAge = 50;    

NSLog(@"  block--->        --->%@", myBlock(@"  ", 16));        

[self printWithName:@"   " age:26 block:^(NSString *str, int age){ 

       return [NSString stringWithFormat:@"        --->    --->%@    %d", str, myAge];   

}]; 

このときの出力は
2015-06-03 23:32:32.533 WXYBlock[3537:237755]   block--->        --->    --->      100

2015-06-03 23:32:32.533 WXYBlock[3537:237755]   block--->        --->    --->       50 

これはなぜですか.
調べてみると、私がまとめた理由はこうです.
blockで外部変数を使用すると、彼はこの変数をコピーし、この変数は読み取り専用です.
したがって、外部変数の変更はblockの内部コピーの変数に影響しません.
コード内のインラインブロックは、変数が変更された後にこの変数を使用するので、影響しません.
blockに変数をコピーさせたくない、内部で使用したい変数と外部で使用したい変数が同じアドレスを指す場合、
変数の前に__を付ける必要がありますblockキーワード.
このように:
__block int myAge = 100; 

出力は次のようになります.
2015-06-03 23:32:32.533 WXYBlock[3537:237755]   block--->        --->    --->      50

2015-06-03 23:32:32.533 WXYBlock[3537:237755]   block--->        --->    --->       50 

なお、特筆すべきは、__を加えてblockキーワードの後、外部変数は読み取り専用ではなく、block内部でも値を変更できます.
//     __block       

__block int otherAge = 100;   

myBlock = ^ (NSString *name, int age){

        otherAge = 99;

        return [NSString stringWithFormat:@"     __block--->%@    %d", name, otherAge];    

};    

NSLog(@"  block--->%@", myBlock(@"  ", 16));        

[self printWithName:@"   " age:26 block:^(NSString *str, int age){

        otherAge = 98; 

        return [NSString stringWithFormat:@"     __block--->%@    %d", str, otherAge];    

}]; 

出力は次のとおりです.
2015-06-03 23:32:32.534 WXYBlock[3537:237755]   block--->     __block--->      99

2015-06-03 23:32:32.534 WXYBlock[3537:237755]   block--->     __block--->       98

#  :    __block   , block            ,     ! 

4.blockループリファレンスの問題
この部分の私の理解はあまり深くないかもしれませんが、以下は私自身の簡単な理解だけを話します.
まずselfクラスでNSStringのプロパティを宣言します
#import@interface ViewController : UIViewController

@property (strong, nonatomic) NSString *myStr;

@end

この属性を初期化
self.myStr = @"myStr";

インラインブロックを使用するもう一つの方法は、便宜上、前に宣言したブロックを使っていますが、パラメータが使えません.
- (void)printWithblock:(WXYTestBlock)block{

    block(@" ", 0);

}

今、blockでselfを使うか、selfを使いたいです.myStr
もしselfのクラスにblockが含まれている場合、blockにはselfが参照されます.
これにより、ループリファレンスが作成されます.
解決策は以下の通り.
//  self self   

// __weak      

__weak ViewController *weakSelf = self;

//  

myBlock = ^ (NSString *name, int age){

NSLog(@"  Block  self--->%@", weakSelf);

NSLog(@"  Block  self   --->%@", weakSelf.myStr);

return @" ";

};

myBlock(@"", 0);

//  

[self printWithblock:^(NSString *name, int age){

NSLog(@"  Block  self--->%@", weakSelf);

NSLog(@"  Block  self   --->%@", weakSelf.myStr);

return @" ";

}];

selfを一つの用途に変換するWeak修飾weakSelfは,ループ参照を避けることができる.
#  :  self   block   ,  block    self      。        ,  block   self     __weak  。

以上は私個人がblockに対して今まですべての理解で、初心者に対して一定の助けがあることを望みます.