简体   繁体   中英

Copy block between objects

I've always thought, that copy would just copy the object. In case of blocks, it's a bit different, but I'm really surprised how it works in following case.

I have and instance objectA and objectB of the following class:

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

objectA is empty. objectB has the values set. In some point of app, I want to discard objectB and leave only objectA , so I need to inject these two values of objectB to 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
}

I'd expect the block to be copied to the new objectA instance and objectB to be released (because there is no reference pointing to it).

But instead, nothing happens. The block, even though it should, is never again evaluated. Should I copy it in another way? Can someone explain what's and why is happening or point to some documentation which will explain it?

-- edit --

Snippet how the block is set:

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

Beside the question in my comment, this likely does not work anyway.

Blocks are not only a snippet of code, but closures. That means that they do a snapshot of the point in time they are created. If such a block refers to objectB at creation time, after copying they will still refer to that object, even you store the block or a copy of it to objectA . (Instance objects does not have identifiers, however, I think I understand what you mean.)

So, having this code:

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

Something will be done with objectB . After copying (here explicitly) …

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

… it is still the same: Something will be done with objectB , because it is still referred by the block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM