iOSでのBlockの正しい使用は、循環参照とCrashを避ける

2409 ワード

Blockの使用は1つの関数に対して、以下は主にblockの使用中に出会った循環引用を説明して、どのように解決する問題は説明します:MRCに続いてアップルはARCを出して、広範な開発者がメモリ管理の問題を解決するのに便利で、以下は主にMRCの時候blockメモリ管理に対して、いくつかの細部はARCに適用しないで、例えばMRCの下でblockでは参照カウントは増加しませんが、ARCでは増加します(下に詳しく説明があります)、ARCでは使用しなければなりません.weak修飾.
Blockの概要
Blockの使用は関数ポインタに似ていますが、関数と最大の違いは、Blockが関数以外、文法の役割ドメイン内の外部変数の値にアクセスできることです.すなわち,Blockは関数の機能だけでなく,関数の実行環境も持ち運ぶことができる.このように理解することができて、Blockは実は2つの部分を含みます:1:Blockが実行するコード、これはコンパイルする時すでに生成したのです;2:Blockの実行に必要なすべての外部変数値を含むデータ構造.Blockは、役割ドメインの近くにある変数の値を使用してスナップショットをスタックにコピーするnoteを確立します.Blockは関数とは異なり、ObjCに似たオブジェクトであり、自動リリースプールを使用してメモリを管理できます(ただし、BlockはObjCオブジェクトと完全に等しくありません.詳細は後述します).
Blockは、関数とは異なり、ObjCのようなオブジェクトであり、自動リリースプールを使用してメモリを管理できます(ただし、BlockはObjCオブジェクトと完全に同じではありません.詳細は後述します).
  • NSGlobalBlock:textセグメントに位置する類似関数;retain,release無効
  • NSStackkBlock:スタック領域にあり、関数が戻るとBlockは無効、retain、releaseは無効、copyの場合のみretainCountプラス1
  • NSMallocBlock:ヒープメモリ、retaiin、release、copyプラス1
  • sumBlock blk1 = ^ long (int a, int b) {
      return a + b;
    };
    NSLog(@"blk1 = %@", blk1);// blk1 = <__nsglobalblock__:/>
    
    
    int base = 100;
    sumBlock blk2 = ^ long (int a, int b) {
      return base + a + b;
    };
    NSLog(@"blk2 = %@", blk2); // blk2 = <__nsstackblock__:/>
    
    BlkSum blk3 = [[blk2 copy] autorelease];
    NSLog(@"blk3 = %@", blk3); // blk3 = <__nsmallocblock__:/>

    なぜblk 1タイプがNSGlobalBlockでblk 2タイプがNSStackBlockなのか?blk 1とblk 2の違いは、blk 1がBlock以外の外部変数を使用していないことであり、Blockは局所変数値のスナップショットを確立する必要がなく、blk 1と関数に何の違いもなく、blk 1が存在するメモリアドレス0 x 47 d 0からコンパイラがblk 1をtextコードセグメントに配置したと推測することである.blk 2とblk 1の唯一の違いは、ローカル変数baseが使用されていることであり、blk 2が定義(定義であり、実行ではないことに注意)されている場合、ローカル変数baseの現在の値はcopyによってスタックに渡され、Blockに定数として使用されます.次のコードが実行され、結果は204ではなく203である.
    テキストアドレス