是否可以在Objective-C中创建"块"对象的类别

Ken*_*ins 12 cocoa objective-c objective-c-blocks

我想通过为Objective-C Blocks创建一个类别来添加函数.

__block int (^aBlock)(int) = ^int( int n ){
    if( n <= 1 ) return n;
    return aBlock( n - 1 ) + aBlock( n - 2 );
};
Run Code Online (Sandbox Code Playgroud)

而不是只允许正[aBlock copy],[aBlock retain],[aBlock release],[aBlock autorelease].我可以这样做:

[aBlock mapTo:anArray];
Run Code Online (Sandbox Code Playgroud)

可能的类别

@interface UnknownBlockClass (map)

- (NSArray *)mapTo:(NSArray *)array_;

@end
Run Code Online (Sandbox Code Playgroud)

Dav*_*ong 13

@pwc是正确的,因为你无法为你看不到的类创建一个类别.

然而...

什么,我要告诉你应该严格用于AS实乃学习,从来没有在任何生产地点进行排序.

  1. 一些运行时内省揭示了一些有趣的信息.有许多类包含单词"Block".他们中有些人看好:__NSStackBlock,__NSMallocBlock,__NSAutoBlock,和NSBlock.
  2. 更多的内省表明,有希望的类继承自 NSBlock

因此看起来任何块都将成为某个实例或子类NSBlock.

您可以在对象上创建方法,如下所示:

@implementation Foo
- (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
}
@end
Run Code Online (Sandbox Code Playgroud)

然后在运行时,您可以将该方法移动到NSBlock该类:

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);
Run Code Online (Sandbox Code Playgroud)

在此之后,块应响应该doFoo消息.

使用您自己承担风险,仅用于实验.


pwc*_*pwc 6

一个块最终成为类型的实例__NSGlobalBlock__,如下面的代码片段所示:

    void (^aBlock)(void) = ^(void) {
        NSLog(@"Hello world");
    };

    // prints "type = __NSGlobalBlock__"
    NSLog(@"type = %@", [aBlock class]);

为了创建类的类,编译器需要能够看到类的原始@interface声明.我找不到声明__NSGlobalBlock__,也许是有充分理由的.

本文本文包含有关块实现的一些有用信息.

至于你原来的观点,为什么不NSArray为你的mapTo方法做一个类别?对于那种功能来说,这似乎是一个更好的地方.

更新

假设您可以向Block对象添加类别.你会如何从类别的方法中调用块?据我所知,调用块的唯一方法是通过()运算符(例如aBlock()).我不认为有一种方法可以从Block对象中分辨出参数的数量和类型.那么,你将什么参数传递给块调用?

我不建议你这样做,但以下工作......

@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];

  • 聪明,是的,但很危险.无法保证各种NSBlock类永远存在于NSObject中...... (2认同)