我已经看到了一些类似于这个问题的SO问题,但它们都涉及单身人士,并且答案都是(正确地)“不要那样做,而是使用dispatch_once()代替。”
在我的特定实例中,我没有制作单例,我需要超类的allocWithZone:
来返回我的子类的实例。
我要做的是:我想对我不拥有的现有库进行扩展。而不是在类别中做一堆行为 - 如果我覆盖现有行为,甚至无法正常工作,因为没有定义调用哪些相同的签名方法 - 我希望它是那样的当有人包含我的(非常小的)类别时,然后拨打
LibObject *myObj = [[LibObject alloc] init];
他们回来了,好像他们打电话一样
LibObject *myObj = [[MyLibObjSubclass alloc] init];
其中LibrarySubclass
是我正在创建的子类。特别是,作为LibObject
的子类的所有库的对象,我希望它们是MyLibObjSubclass
的子类。
我已经搞砸了混合和类别以及我能想到的其他一切,但我总是遇到两个问题之一:
[MyLibObjSubclass alloc]
致电[LibObject alloc]
致电[MyLibObjSubclass alloc]
等,或LibObject
的子类的所有内容,而不是MyLibObjSubclass
的子类及其新行为,它只是 a MyLibObjSubclass
,没有任何其他行为。对于第二个问题,举例来说,假设我试图将所有UIView
- s覆盖为MyView
- s,其中MyView
是{UIView
的子类1}}。问题在于,当我尝试分类时(作为UIView+MyShim
的一部分),那么这一行:
UILabel *label = [[UILabel alloc] init];
而不是返回作为MyView的子类的UILabel
- > UIView - > UIResponder - > NSObject,它只返回MyView
,例如,它不包含text
属性,因此所有UILabel
- s都被破坏。
所以我的问题是:我该怎么办?
谢谢!
答案 0 :(得分:3)
听起来你想要修改类层次结构:
CCResponder
└─ CCNode
├─ CCControl
└─ CCSprite
到此:
CCResponder
└─ MyResponder
└─ CCNode
├─ CCControl
└─ CCSprite
由于不推荐class_setSuperclass
,因此没有受支持的方法在运行时进行更改。
(注意:是的,这正是我希望做的.~Ollie。)
您是否考虑过只修改Cocos2D源代码?短期来说,这应该是最简单的方法。如果您需要的是足够的,也许您可以将您的更改合并到上游。或者也许你可以添加上游接受的钩子,并使用这些钩子做你需要的。
如果您将代码保存在git中,那么我建议使用git-subtree扩展将Cocos2D源代码导入项目的存储库。这样可以很容易地跟踪您对Cocos2D的本地更改,并在您想要导入更新版本时重新应用它们。
如果这对你不起作用,我认为你应该把它搞砸,然后对你想要改变行为的方法进行调整。
如果您是一个贪婪的惩罚者,您可以在运行时根据需要创建每个CCResponder
子类的新子类。你最终会得到这样的层次结构:
CCResponder
└─ CCNode
├─ CCControl
│ └─ hacked_CCControl
└─ CCSprite
└─ hacked_CCSprite
(我知道CCControl
不是你可能直接实例化的东西,而是让我们假装。)
我认为这是可能的,但非常复杂。要做到这一点,请与{您自己的} +[CCResponder alloc]
混合+[CCResponder allocHack]
。你会实现这样的东西:
static Class createHackedClassForClass(Class originalClass) {
NSString *name = [@"hacked_" stringByAppendingString:NSStringFromClass(originalClass)];
Class hackedClass = objc_allocateClassPair(originalClass, name.UTF8String, 0);
// Here add methods as necessary to hackedClass using class_addMethod.
objc_registerClassPair(hackedClass);
return hackedClass;
}
+ (void)allocHack {
static NSMutableDictionary *hackedClassForClass = [NSMutableDictionary dictionary];
Class hackedClass = hackedClassForClass[self];
if (hackedClass == nil) {
hackedClass = createHackedClassForClass(self);
hackedClassForClass[self] = hackedClass;
}
return class_createInstance(hackedClass, 0);
}
我没试过这个,所以我不知道它是否有任何重大问题。它至少会使调试变得比仅修改Cocos2D源代码更难。