5

ブロックへの強い参照を持つオブジェクトがあるとします。そのブロックの実行中に、強い参照がnilに設定されます。ブロックは実行を終了することが保証されていますか、それともクラッシュを引き起こす可能性がありますか?exc-bad-accessエラーを確認しましたが、確実に生成できないため、なぜポップアップするのか正確にはわかりません。

例えば:

-(void)method
{
    self.block = ^{
        //code
        self.block = nil;
        //more code - crash here?
    }
}

-(void)otherMethod
{
    block();
}
4

3 に答える 3

3

ドキュメントは、実行中にブロックが保持されることを保証していないようです。逆に、などのGCD呼び出しのドキュメントは、そのdispatch_asyncような保証を行います。そのことから、ブロックへの通常の呼び出しがそれを保持するとは想定できないように思われます。

したがって、コードではおそらく次のようにします。

-(void)otherMethod
{
    dispatch_block_t localBlock = Block_copy(block);
    localBlock();
    Block_release(localBlock);
}
于 2012-09-05T00:42:24.540 に答える
3

私はついにこの質問に対して満足のいく答えが得られたと信じています。これはすべてARCのコンテキストにあることに注意してください。

ブロックは、実行中に割り当てが解除される可能性があります。ブロックは通常どおり実行を継続しますが、キャプチャされた変数へのポインタはいずれも疑わしい(そして潜在的に危険)ようになります。

ObjectAにcompletionという名前のブロックコピープロパティがあるとします。

@property (nonatomic, copy) void (^completion)();

...割り当ては次のようになります。

__weak ObjectA * weakSelf = self;
self.completion = ^{
    weakSelf.completion = nil;
    [weakSelf doSomethingElse];
};

ブロックがそのように呼ばれる場合...

-(void)method
{
    _completion(); //directly uses ObjectA's instance of the block
}

...次に、ブロックのこのインスタンスへの参照が他にないと仮定すると、ブロックは割り当て解除され、キャプチャされた変数weakSelfはnilになります。doSomethingElseが呼び出されることはありません。これを回避する最善の方法は、アクセサを使用してブロックを呼び出すことです。これにより、スタックに新しいコピーが割り当てられます。元の変数の割り当ては解除されますが、新しいコピーとそのキャプチャされたすべての変数は、現在のコンテキストで存続します。

-(void)method
{
    self.completion(); //uses new copy of the block
}
于 2013-06-25T14:54:22.813 に答える
1

ブロックを実行するメソッドが、ブロックへの参照がまだ存在するかどうかを最初にチェックしない場合、クラッシュが発生する可能性があります。メソッドでこれらのクラッシュが発生した可能性があります。これは、このようなチェックが欠落していたためです。

- (void)methodWithBlock:(void (^)(void))block
{
   if (block) // this check is to prevent crashes when calling to a released block pointer ...
   {
      block();
   }
}

このようなチェックが欠落しているコードに遭遇した可能性があり、これにより、経験したクラッシュが発生した可能性があります。私は確かに同じことを経験しました。

于 2012-09-04T23:57:54.170 に答える