Reputation: 3387
I want to declare a block type which take one parameter that is the same block type. It's just like this:
typedef void (^BlockInBlock) (BlockInBlock block);
I know the declaration is not valid. But I wonder if there is any possible way to implement recursive block which take just one parameter that is the same block type.
I'm trying finding a way to implement aspect-oriented programming (AOP) in Objective-C using block. Here are my questions about how to implement that.
Further Question 1:
How to implement a variadic function which takes many Blocks I described above and is ended up with nil
, and I could invoke that function with many blocks until meets nil? It would be like this:
@interface NSObject(AOP)
- (void) invokeBlockInBlock:(BlockInBlock) headBlock, ...{
va_list blockList;
va_start(blockList, headBlock);
// Invoke recursive blocks here until the value of va_arg(blockList, BlockInBlock) is nil
// it would be like: block1(self, block2(self, block3(self, block4(...))));
va_end(blockList);
}
@end
Further Question 2:
What if the recursive block has a return value?
Additional Question about C language:
Is it possible to declare a C function which take one parameter that is a C function pointer, and that C function pointer's function also takes another C function pointer?
Upvotes: 8
Views: 4273
Reputation: 24041
that may be similar you are looking for:
typedef void (^Block)(id);
literally, it will cause an infinite recursive loop:
Block _block;
_block = ^(Block block) {
if (block) block(block);
};
_block(_block);
however the parameter could be any id
not only the exact same Block
, but it represents how you pass the same block as parameter for the same block.
so, that would be the idea.
Upvotes: 11
Reputation: 162712
It is much easier to do this by capturing the block in an __block reference. Actually, forward declaration of generic types in C are simply not supported. So, this may be the only solution?
__block void(^strawberryFields)();
strawberryFields = ^{ strawberryFields(); };
strawberryFields();
Note that if you are planning on dispatching that block asynchronously, you must copy it prior to assignment (this might no longer be necessary under ARC):
__block void(^strawberryFields)();
strawberryFields = [^{ strawberryFields(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
strawberryFields);
Upvotes: 4