1

私はいつも、それcopyはオブジェクトをコピーするだけだと思っていました。ブロックの場合は少し違いますが、以下の場合の動きには本当に驚きました。

次のクラスのインスタンスとインスタンスがありますobjectAobjectB

@interface MyObject : NSObject
@property(nonatomic, copy) void (^myHandler)(CGFloat progress);
@property(nonatomic) CGFloat progress;
@end

objectA空です。objectB値が設定されています。objectBアプリのある時点で、破棄して のみを残したいobjectAので、 to の次の 2 つの値を注入する必要がありobjectBますobjectA

MyObject *objectA = [MyObject new];
if (nowIWantToGetRidOfB) {
    objectA.progress = objectB.progress;
    objectA.myHandler = objectB.myHandler;
    objectB.myHandler = nil;
    objectB = nil; // that's just an example to show it gets released after this code
}

objectAブロックが新しいインスタンスにコピーされ、objectB解放されることを期待しています (それを指す参照がないため)。

しかし、代わりに、何も起こりません。ブロックは、評価される必要がありますが、再度評価されることはありません。別の方法でコピーする必要がありますか?誰かが何が起こっているのか、なぜ起こっているのかを説明したり、それを説明するドキュメントを指摘したりできますか?

- 編集 -

ブロックの設定方法のスニペット:

MyObject *objectB = [MyObject new];
objectB.progress = 0.5f;
[objectB setProgressHandler:^(CGFloat progress) {
    NSLog(@"example");
}];
4

1 に答える 1

1

私のコメントの質問に加えて、これはとにかくうまくいかない可能性があります。

ブロックはコードのスニペットであるだけでなく、クロージャでもあります。つまり、作成された時点のスナップショットを作成します。そのようなブロックobjectBが作成時に参照されている場合、コピーした後も、ブロックまたはそのコピーをobjectA. (インスタンス オブジェクトには識別子がありませんが、おっしゃる意味は理解できると思います。)

したがって、このコードを持つ:

MyObject *objectB = …;
objectB.handler = ^(CGFloat progress)
{
  … objectB …
}

で何とかなるobjectB。コピー後 (ここでは明示的に) …</p>

MyObject *objectA = …;
objectA.handler = objectB.handler;

objectB…それはまだ同じです:ブロックによってまだ参照されているため、 で何かが行われます。

于 2016-04-04T17:13:03.057 に答える