【问题标题】:Add a method dynamically to an object in Objective-C?在Objective-C中动态地将方法添加到对象?
【发布时间】:2013-04-13 09:01:01
【问题描述】:

我想在 Objective-C 中做这个 JavaScript:

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

这可能吗?还是只能将方法添加到 Objective-C 中的 class 而不能添加到对象? IE。我找到了class_addMethod,但我想要一种方法在同一类的不同实例上拥有相同选择器的不同实现。

这是可能的还是我是 SOL?

【问题讨论】:

    标签: objective-c dynamic reflection


    【解决方案1】:

    在 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
    

    【讨论】:

    • 谢谢,这绝对有帮助。我现在的想法是动态创建单个类,在该类上设置选择器的实现,然后将通用实例(为处理此问题而编写的类)上的调用转发到该内部特定类实例。
    • 我担心的是,一旦创建和注册了一个类,似乎没有任何方法可以动态地销毁或解除分配。
    • 你是对的。类一旦创建就不能删除。实例不保留其类,因此运行时无法确保删除类是安全的。
    【解决方案2】:

    不可能直接。在 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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 1970-01-01
      • 2013-07-15
      • 2012-01-12
      • 1970-01-01
      • 1970-01-01
      • 2016-02-02
      相关资源
      最近更新 更多