19

ブロックを理解しようとしています。メソッドに直接渡されると、通常どおり使用する方法がわかりました。私は今、ブロックを取得し、それを (たとえば) インスタンス変数に格納し、後で呼び出すことに興味があります。

ブロック プログラミング ガイドでは、Block_copy/retain を使用してブロックをコピーすることで、これを実行できるように思われますが、実行しようとするとプログラムがクラッシュします。

- (void) setupStoredBlock
{
    int salt = 42;
    m_storedBlock = ^(int incoming){ return 2 + incoming + salt; };
    [m_storedBlock retain];
}

私は後でそれを呼び出そうとします:

- (void) runStoredBlock
{
    int outputValue = m_storedBlock(5);
    NSLog(@"When we ran our stored blockwe got back: %d", outputValue);
    [m_storedBlock release];
}

誰にも洞察がありますか?(または、ブロックで得られないものはありますか?)

どうもありがとうございました!

4

4 に答える 4

30

代わりにこれを行う必要があります。

- (void) setupStoredBlock
{
    int salt = 42;
    m_storedBlock = Block_copy(^(int incoming){ return 2 + incoming + salt; });
}
于 2010-04-17T17:39:01.213 に答える
6

• すべてのローカル変数と同様に、非静的ブロックはスタック上に存在し、静的と宣言されていない他のローカル変数と同様にスタックからポップされます。

• Block_copy() は、すべての malloc インスタンスが存在するスタックからヒープにブロックをコピーします。また、すべての new/copy メソッドと同様に、Block_copy() は保持カウントが 1 のヒープ割り当てオブジェクトを返します。ブロックは ObjectiveC オブジェクトですが、通常のオブジェクトのようには適合しません。したがって、Block_Release() と目的の解放方法に違いはないはずです。

• この例では、ブロック インスタンスのコピー メソッドを使用します。Block_copy() の結果を id に割り当てるには、間違ってほしくない型キャストが必要だからです。copy メソッドを使用すると、ブロック変数を ID に直接割り当てることができます。

 - (void) setupStoredBlock
{
    int zStackLocalVariable = 42;
    iHeapAllocatedVariable = [^int(int aMore){ return zStackLocalVariable + aMore; } copy];
}

• オブジェクトを static と宣言するということは、それをコード自体に物理的に割り当てる必要があるということです。static と宣言されたブロックは、それ自体のスコープ外の変数にアクセスすることをコンパイラによって禁止されています。静的ブロック宣言の要件により、スタック上のブロックはヒープ内のブロックとは何らかの形で異なると想定しています。

• ブロックは、クラス名とその他の関連情報をまだ取得しようとしていないクラスのオブジェクティブ オブジェクトですが、Protocol、Object、およびその他の非表示の ObjectiveC クラスと同様に、NSObject に準拠していません。ただし、すべての ObjectiveC オブジェクトと同様に、保持/解放に準拠する必要があります。ARC は保持/解放の等価性を Core Foundation オブジェクトにも拡張します。おそらく、今ではないにしても、最終的には malloc/free 割り当てに拡張されます。

• 私はmikeash.comを徹底的に調査する真の動機を待ち望んでいます。なぜなら、Appleは物理的な意味がほとんどない超理論的な次元に私たちを引き留めたいからです。

ARC とブロックについてもここで説明します

于 2013-01-21T02:45:42.390 に答える
6

ブロックを残しておきたい場合は、ブロックをコピーします。自動解放するか、使い終わったら解放します。スペルするのに長い道のりが必要な場合は、それを保持してください/* NOP */

@interface Foo : FooSuper {}
@property(copy) int (^storedBlock)(int);
@end

@implementation Foo
@synthesize storedBlock = mStoredBlock;

- (void)setupStoredBlock {
    self.storedBlock = ^{/*...*/};
    // or: mStoredBlock = [^{/*...*/} copy];
    // but this simple implementation violates the atomicity contract
}

- (void)runStoredBlock {
    int result = self.storedBlock(5);
    NSLog(@"%s: result = %d", __func__, result);
}
@end
于 2010-04-21T05:04:22.650 に答える
4

最近の WWDC (2010) では、このテーマに関する非常に優れたプレゼンテーションがありました。ブロックの実装方法と、Block_copy を使用する必要がある理由について説明しました。次のプレゼンテーションからムービーをダウンロードでき ます

于 2010-11-02T20:23:43.553 に答える