在Objective-C中动态添加方法到对象?

时间:2013-04-19 21:12:58

标签: objective-c dynamic reflection

我想在Objective-C中执行此JavaScript:

var obj = {};
obj.myFunc = function() { ... };

这可能吗?或者只能将方法添加到Objective-C中的而不是对象?即我发现class_addMethod,但我想要一种方法在同一个类的不同实例上使用相同选择器的不同的实现。

这可能还是我SOL?

2 个答案:

答案 0 :(得分:5)

在Objective-C中,方法(甚至实例方法)仅在类上定义,而不是在单个对象上定义。

您可以使用objc_allocateClassPair在运行时创建新类,并向该类添加方法。您可以使用object_setClass在运行时更改对象的类。如果你决定调查一下,你会想要对“isa-swizzling”做一些研究。如果你想在你将与KVO一起使用的对象上使用它,那就特别有问题了。

如果您可以简单地更改API以使用块,那将会简单得多。例如:

@interface MyObject : NSObject

- (void)myMethodWithString:(NSString *)string;

typedef void (^MyMethodBlock)(NSString *string);

@property (nonatomic, copy) MyMethodBlock myMethodBlock;

@end

@implementation MyObject

@synthesize myMethodBlock = _myMethodBlock;

- (void)myMethodWithString:(NSString *)string {
    MyMethodBlock block = self.myMethodBlock;
    if (block) {
        block(string);
    }
}

@end

答案 1 :(得分:1)

不可能直接。在JavaScript中,对象继承自其他对象,而在Objective-C中,继承是通过类实现的。

我不明白为什么你还需要这个,可能你有一个设计问题而且你向我们展示了一个XY问题。然而,这是一个我可以想象的非常难看的解决方案,仅用于教育用途。仅适用于只采用一个参数的方法。

id dispatch_helper(id obj, SEL sel, id arg)
{
    id (^blk)(id, SEL, id) = objc_getAssociatedObject(obj, sel);
    return blk(obj, sel, arg);
}

void object_addMethod(id obj, SEL sel, IMP imp)
{
    class_addMethod(object_getClass(obj), sel, dispatch_helper, "@@:@");
    objc_setAssociatedObject(obj, sel, ^(id o, SEL s, id a) {
        return IMP(o, s, a);
    }, OBJC_ASSOCIATION_COPY_NONATOMIC);
}