16

最近、ブロックの次のプロパティ宣言を示すApple ドキュメントに出くわしました。

@interface XYZObject : NSObject
@property (copy) void (^blockProperty)(void);
@end

また、この記事では次のように述べています。

注: 元のスコープ外でキャプチャされた状態を追跡するには、ブロックをコピーする必要があるため、プロパティ属性として copy を指定する必要があります。これは自動的に行われるため、自動参照カウントを使用する際に心配する必要はありませんが、結果の動作をプロパティ属性で表示することをお勧めします。詳細については、ブロック プログラミングのトピックを参照してください。

提案されたBlocks Programming Topicsも読みましたが、そこに関連するものは見つかりませんでした。

ブロック プロパティを「コピー」として定義することがベスト プラクティスである理由については、まだ興味があります。良い答えがあれば、ARC と MRC の違いがあれば区別してみてください。

ありがとうございました

4

3 に答える 3

25

デフォルトでは、ブロックはスタック上に作成されます。つまり、作成されたスコープ内にのみ存在します。

後でそれらにアクセスする場合は、copyメッセージをブロック オブジェクトに送信してヒープにコピーする必要があります。ARC は、ブロックが作成されたスコープ外でアクセスする必要があることを検出するとすぐに、これを行います。ベスト プラクティスとして、ブロック プロパティをコピーとして宣言します。これは、自動メモリ管理下にある必要があるためです。

スタックとヒープの詳細については、Mike Ash によるObjective-C の Stack and Heap Objects を参照してください。

于 2013-02-01T16:10:15.753 に答える
7

デフォルトでは、ブロックはスタックに割り当てられます。スタック割り当てはヒープ割り当てよりもはるかに安価であるため、これは最適化です。スタック割り当てとは、デフォルトでは、ブロックが宣言されているスコープが終了するとブロックが存在しなくなることを意味します。そのため、セマンティクスを持つブロック プロパティはretain、もはや存在しないブロックへのダングリング ポインターになります。

ブロックをスタックからヒープに移動するには (そして、通常の Objective-C のメモリ管理セマンティクスと有効期間を延長するために) [theBlock copy]Block_copy(theBlock)、 などを介してブロックをコピーする必要があります。保持/解放することで必要になります。-retain(はい、これは ARC にも当てはまります。/を自分で呼び出す必要はありません-release。)

したがって、セマンティクスを使用してブロック プロパティを宣言しcopy、プロパティが設定されたときにブロックがコピーされるようにして、スタックベースのブロックへのダングリング ポインターを回避します。

于 2013-02-01T16:11:54.490 に答える
6

あなたが言及する「ベストプラクティス」は、「ARCはここに何を書いても、魔法のようにブロックをコピーするので、コードを見て将来の世代を混乱させないように、明示的に「コピー」を書くのが最善です」と簡単に言います。

説明は次のとおりです。

通常、ブロックをコピー(または保持)する必要はありません。宣言されたスコープの破棄後にブロックが使用されることを期待する場合にのみ、コピーを作成する必要があります。コピーすると、ブロックがヒープに移動します。
–ブロックプログラミングトピック:ブロックの使用、ブロックのコピー

明らかに、プロパティにブロックを割り当てることは、それが宣言されたスコープが破棄された後に使用できることを意味します。したがって、Blocks Programming Topicsによると、そのブロックは。を使用してヒープにコピーする必要がありますBlock_copy

しかし、ARCはあなたのためにこれを処理します:

リターンなどのARCモードでブロックをスタックに渡すと、ブロックは「正常に機能」します。もうBlockCopyを呼び出す必要はありません。
– <a href="https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html"rel="noreferrer">ARCへの移行

これはブロックのセマンティクスに関するものではないことに注意してください。retain(間もなくポップされる)スタックからヒープに移動せずに、ブロックのコンテキストが存在する方法はありません。したがって、修飾する属性に関係なく@property、ARCはブロックをコピーします。

于 2013-02-01T16:27:37.793 に答える