OCにおけるblockの使用及び注意

2791 ワード

基本概念
blockはコードセグメントであり、実行可能なコードであり、iOS 4以降に追加された構文と呼ばれるプログラミング言語もあります.
blockはフォーマットのCレベルの構文と実行メカニズムを実行し、標準的なC関数と類似しています.異なる点は、実行可能なコードのほかに、スタック、スタックメモリにバインドされた変数も含まれていることです.そのため、blockにはステータスデータのセットが含まれています.これらのデータは、プログラム実行時に動作に影響を与えるために使用されます.APIに転送できる関数文をblockで書くことができ、選択的に保存することができ、マルチスレッドをコールバックとして使用することができます.blockは特に役に立ちます.blockにはコールバック期間のコードと実行中に必要なデータが含まれているからです.OC,C++はいずれもCから派生しているため,blockはこの3つの言語を互換化するように設計されている.
OCではblockを属性,メソッドパラメータ,一時変数などとして定義できる.
blockの基本形式
//
パラメータなし戻り値なし
void
(^demo1)() = ^(){     };
//
パラメータなし戻り値
void
(^demo2)(
int
,
int
) = ^(
int
a,
int
b){     };
//
戻り値なし
int
(^demo3)() = ^(){      
return
0
; };
//
パラメータ付き戻り値
int
(^demo4)(
int
,
int
) = ^(
int
a,
int
b){    
return
a+b;
};
ブロックのtypedef
//
ひとつあげる
int
タイプ、2つあります
int
タイプパラメータの
block
別名
temp
、注意:この書き方はデータ型で直接作成できます.
block
あ、これはマクロとは別です.マクロはコンパイラの特性で、役割は置換だけです.
typedef
int
(^temp)(
int
,
int
);
int
main(
int
argc,
const
char
* argv[]) {    
@autoreleasepool
{        
temp
sum = ^(
int
a,
int
b){                        
return
a+b;         };                
NSLog
(
@"%d"
,sum(
1
,
2
));     }    
return
0
;
}
ブロックパラメータとして定義- (void)callDemo:(void(^)())task { // block, task(); } ブロックパラメータとして定義@interface ViewController ()

@property (nonatomic,assignint num;
/// block
@property (nonatomic,copyvoid (^PropertyBlock)();

@end

block外部変数へのアクセスと変更
注意:デフォルトではblock内では外部変数の変更は許可されていません.変更するには_blockは変数を表示し、コンパイラにこの変数がblock内部で修正操作されていることを知らせます.
ARC環境でのblockアクセスと外部変数の変更
  • 単純にブロックを定義すると、ブロックはグローバル領域
  • に格納される.
  • blockが外部変数にアクセスするとき、外部変数のメモリに格納される領域の変化:
  • アクセス前変数はスタック領域に格納、アクセス時変数はスタック領域に格納、アクセス後変数はスタック領域
  • に格納.
  • block外部変数を変更する場合、外部変数のメモリに格納される領域の変化:
  • 修正前変数はスタック領域に格納(__blockで修飾する格納位置は影響を受けない)、修正時変数はスタック領域に格納、修正後変数はスタック領域
  • に格納.

  • MRC環境でのblockアクセスと外部変数の変更
    MRCの環境ではblockが外部変数にアクセスして修正し、外部変数の格納領域は変更されず、スタック領域に格納されます.
    blockはOCで属性をcopyで修飾するように定義します
    MRCの環境では、ブロックはスタックに保存されており、グローバル共有はできません.グローバル共有を実現するには、そのcopyをスタックに置く必要があります.これが原因です.ARC環境ではstrongとcopyの効果は同じですが、アップルの公式推奨はcopyで修飾します.