Can Obj-C Block execute by itself?

This is an extension of this quest: Is it possible to create the category "Block", an object in Objective-C .

Basically, although it seems possible to create a category on blocks, either through NSObject or NSBlock, it's hard for me to understand how a block can evaluate itself. An example given in the answer to the last question:

- (void) doFoo { //do something awesome with self, a block //however, you can't do "self()". //You'll have to cast it to a block-type variable and use that } 

It is understood that you can somehow include self in a block variable, but how to execute the block itself? For example, let's say I made a category in NSBlock and in a method did:

 NSBlock* selfAsBlock = (NSBlock*)self; 

Is there a message that I can send to selfAsBlock to evaluate the block?

+7
source share
2 answers

Assumes you can somehow include self in a block variable

Like this:

 - (void)doFoo { // Assume the block receives an int, returns an int, // and cast self to the corresponding block type int (^selfBlock)(int) = (int (^)(int))self; // Call itself and print the return value printf("in doFoo: %d\n", selfBlock(42)); } 

Please note that (in most cases) you need to correct the block signature so that the compiler can configure the call site in accordance with the target ABI platform. In the above example, the signature is an int return type, the only parameter of type int .

Full example:

 #import <Foundation/Foundation.h> #import <objc/runtime.h> @interface Foo : NSObject - (void)doFoo; @end @implementation Foo - (void)doFoo { // Assume the block receives an int, returns an int, // and cast self to the corresponding block type int (^selfBlock)(int) = (int (^)(int))self; // Call itself and print the return value printf("in doFoo: %d\n", selfBlock(42)); } @end int main(void) { [NSAutoreleasePool new]; // From Dave answer Method m = class_getInstanceMethod([Foo class], @selector(doFoo)); IMP doFoo = method_getImplementation(m); const char *type = method_getTypeEncoding(m); Class nsblock = NSClassFromString(@"NSBlock"); class_addMethod(nsblock, @selector(doFoo), doFoo, type); // A block that receives an int, returns an int int (^doubler)(int) = ^int(int someNumber){ return someNumber + someNumber; }; // Call the category method which in turn calls itself (the block) [doubler doFoo]; return 0; } 
+7
source

NSBlock has an invoke method that can be used to invoke a block.

 NSBlock* b = ^() { /* do stuff */ }; [b invoke]; 

Note that this is a private, undocumented method.

+4
source

All Articles