将数据与动态生成的子类相关联的最佳方法

时间:2014-01-27 18:01:04

标签: objective-c

此代码必须能够在iOS 6.1及更高版本上运行。

我有一个基类,它在运行时使用objc_allocateClassPair动态子类化。基类几乎包含所有逻辑(在类方法和实例方法中),子类应该只提供一些信息,这些信息应该在超类方法中很容易获得,用于实现逻辑。这段数据作为参数传递给基类的类级工厂方法,该方法生成一个包含数据的新子类。所以,不知何故,我需要将一段数据与这个生成的子类相关联,我不知道究竟是怎么做到的。我有一些想法:

  • 在生成的类中添加一个类字段 - 我不确定Obj-C是否支持这个,有class_getClassVariable但我没有看到实际设置它的选项 - 我应该在生成的元类上设置一个iVar子类?
  • 使用objc_setAssociatedObject将此数据与生成的类对象相关联,然后通过objc_getAssociatedObject在超类方法中使用它 - 这将导致我必须使用丑陋的运行时方法调用来在需要时获取数据,我更喜欢使用标准语法(这也是类字段的一个问题,因为即使Obj-C运行时支持类字段,我认为语法也没有;但如果没有其他方法,那就OK)
  • 添加一个返回数据的类方法;我将在超类中实现一个虚拟方法,它不执行任何操作/抛出异常,一旦生成了子类,我将使用method_setImplementation设置此方法的实现;这里我有一个问题,因为我需要关联的数据必须在设置实现时作为参数传递给这个新实现;基本上,我需要创建一个函数,它将id self和SEL _cmd作为参数并返回我的数据;我不知道如何在Obj-C中做到这一点,在其他语言中我可以使用currying:

    MyData* getMyData(MyData* myData, id self, SEL _cmd) {
        return myData;
    }
    
    ...
    
    IMP createImp(MyData *myDataInstance) {
        return curry(getMyData, myDataInstance);
    }
    

    然后使用createImp的返回值作为method_setImplementation的第二个参数,基本上创建一个类级别的getter - 问题是我不知道如何在Objective-C中执行此操作,更不用说这是一个好主意

那么,编写我想要实现的内容的最佳方法是什么?

修改

作为对用例评论的回复: 基类有conformsToProtocol,respondsToSelector和instancesRespondToSelector(类方法)等方法,需要使用协议类型(我试图关联的数据)。为了实现这样的协议方法,基类的子类在运行时生成,并使其符合作为参数传递给工厂方法的协议 - 伪代码:

    + (instancetype)implementorFor:(Protocol *)protocol {
        1. generate unique class name
        2. check if generatedClass for the protocol already exists, use it if it does
        3. if generatedClass doesn't exist - allocateClassPair
          4. addProtocol(generatedClass, protocol)
          5. registerClassPair(generatedClass)
        6. return [[generatedClass alloc] initInstance]
    }

协议方法是使用forwardInvocation和系列实现的(我不允许在这里给出太多细节) - 它都像魅力一样,但直到现在,我都不支持instancesRespondToSelector方法(和其他自定义)类级方法)因为实现的协议类型是在initInstance方法中设置的实例变量,而不是类变量 - 事情发生了变化,现在我需要生成的类来知道它符合的协议。这就是问题的原因 - 如何让班级知道它的协议。 所以,这是一个已经在工作的专有应用程序,虽然我很想学习更好的方法来实现这一点(即通常实现某些协议类型),但为时已晚(除非它是巧妙的,否则我就不会去睡觉了)直到我用更好的解决方案替换当前的解决方案)。即使这个用例被认为是可疑的,我仍然想知道如何将数据与类关联(即创建一个类字段)。在发布此问题之后阅读了一些内容后,相关对象似乎就成了一条路。

0 个答案:

没有答案