Is it possible to create a category of the “Block” object in Objective-C

前端 未结 5 1494
梦如初夏
梦如初夏 2021-02-07 20:40

I would like to add functions by creating a category for Objective-C Blocks.

__block int (^aBlock)(int) = ^int( int n ){
    if( n <= 1 ) return n;
    return         


        
5条回答
  •  太阳男子
    2021-02-07 21:16

    A block winds up being an instance of type __NSGlobalBlock__, as seen in the following snippet:

        void (^aBlock)(void) = ^(void) {
            NSLog(@"Hello world");
        };
    
        // prints "type = __NSGlobalBlock__"
        NSLog(@"type = %@", [aBlock class]);
    

    In order to create a category of a class, the compiler needs to be able to see the original @interface declaration of the class. I can't find the declaration for __NSGlobalBlock__ and probably for good reason.

    This article and this article contain some useful information about the implementation of blocks.

    To your original point, why not just make a category of NSArray for your mapTo method? It seems like a better place for that sort of functionality.

    Updated

    Let's say you can add a category to the Block object. How would you invoke the block from the category's method? To the best of my understanding, the only way to invoke a block is via the () operator (e.g., aBlock()). I don't think there's a way to tell from the Block object the number and types of parameters. So, what arguments would you pass in to the block invocation?

    I'm not recommending you do this, but the following works...

    @interface NSObject (BlockExtension)
    - (void)foo;
    @end
    
    @implementation NSObject (BlockExtension)
    - (void)foo
    {
        // not sure how else to determine if self is a Block since neither
        // __NSGlobalBlock__ nor any of its superclasses (except NSObject) 
        // are accessible to the compiler
        if ([[[self class] description] isEqual:@"__NSGlobalBlock__"])
        {
            NSLog(@"foo");
            // now what?
            // can't call self(), it doesn't compile
            // how else can I invoke this block?
        }
    }
    @end
    
    ...
    
    void (^aBlock)(void) = ^(void) {
        NSLog(@"Hello world");
    };
    
    // prints "foo"
    [aBlock foo];
    

提交回复
热议问题