Encoding an Objective-c Block?
Asked Answered
I

1

17

Is it possible to encode an Objective-C block with an NSKeyedArchiver?

I don't think a Block object is NSCoding-compliant, therefore [coder encodeObject:block forKey:@"block"] does not work?

Any ideas?

Irishirishism answered 31/1, 2010 at 18:20 Comment(0)
M
19

No, it isn't possible for a variety of reasons. The data contained within a block isn't represented in any way similar to, say, instance variables. There is no inventory of state and, thus, no way to enumerate the state for archival purposes.

Instead, I would suggest you create a simple class to hold your data, instances of which carry the state used by the blocks during processing and which can be easily archived.

You might find the answer to this question interesting. It is related.


To expand, say you had a class like:

@interface MyData:NSObject
{
    ... ivars representing work to be done in block
}

- (void) doYourMagicMan;
@end

Then you could:

MyData *myWorkUnit = [MyData new];

... set up myWorkUnit here ...

[something doSomethingWithBlockCallback: ^{ [myWorkUnit doYourMagicMan]; }];

[myWorkUnit release]; // the block will retain it (callback *must* Block_copy() the block)

From there, you could implement archiving on MyData, save it away, etc... The key is treat the Block as the trigger for doing the computation and encapsulate said computation and the computation's necessary state into the instance of the MyData class.

Miterwort answered 31/1, 2010 at 18:47 Comment(3)
Thank you for the answer, I think I understand why it is not straightforward to simply encode them. However I am confused about your suggestion of using a class to hold the state used by blocks. Would you be able to expand on how to implement that? In my situation I have basic void callback blocks, i.e. void^{ do_stuff; }. Thanks!Irishirishism
It is counterintuitive that a block can easily be an instance variable... yet cannot be un/archived. By counterintuitive, I mean, lame. Upvoted for being the only answer, with the caveat that I'd guess that there IS indeed a way... somehow, somewhere.Seventeenth
@alexgray Tons of objects can be instance variables that cannot be archived/unarchived (every class that doesn't support NSCopying). And what would it even mean for a block to be archivable? Would all the captured objects have to be archivable, too? What if it captures a random struct? Gotta archive that, too? What about architecture/endian dependencies? Those are automatically handled by the archiver APIs. Would blocks then have to grow the ability to implement custom archiving? Beyond being a nightmare to maintain, that would be very hard to support in the 'kit (with little ROI).Miterwort

© 2022 - 2024 — McMap. All rights reserved.