Override a method in a single object instance
Am not sure how to put this, and I couldn't find the answer because of my inability to find the words to express what am looking for. (!)
In Java, I used to do something like this (I don't remember):
JPanel myButton = new JPanel("Press me"){
public void add(JComponent component){
//override add method
}
};
But, i coul开发者_如何学Pythondn't find how to do this in Objective-C .. What I found in my search was categories and weird ^{} symbols ...
So, how can I override method(s) in a newly created object?
(For example, override -(BOOL)isEqual;
in a newly created NSString*
?)
Am sorry if the question is a bit vague..
EDIT:
Obviously, without subclassing :)
EDIT:
Might as well post my problem in case someone has a better idea:
I have a few CCTransitions in COCOS2D, and I want to be notified when the transition ends .. The thing is, as soon as the transition ends, the -(void)finish; method is invoked (which is part of the CCTransition class structure)
I would really want to avoid subclassing the CCTransition class, and override the finish method to do my logic when the transition ends :)
EDIT:
-(void)onEnterTransitionDidFinish; ... I can't believe something as awesome as that existed and I haven't came across it while searching......
Which means, instead of subclassing CCTransition, override this method in my CCNode subclass :D!
It's still not going to be very clean, but assuming you're willing to concentrate the ugliness, you could do something like (untested):
Method methodToReplace =
[targetClass instanceMethodSignatureForSelector:@selector(methodToReplace)];
IMP implementationToSet =
[someProxyClass instanceMethodForSelector:@selector(implementationYouWant)];
method_setImplementation(methodToReplace, implementationToSet);
Relevant reference documentation is the Objective-C Runtime Reference and, optionally, the NSObject Class Reference (because it makes a few things slightly neater, though e.g. you could use class_getInstanceMethod
from the runtime rather than instanceMethodSigntureForSelector:
).
Note that you'll have no way to call the original implementation if you use exactly that recipe. method_setImplementation returns the old implementation, it's generally wise to add that to the class under a brand new selector and call that instead.
For reference, I've had a legitimate reason to do this sort of thing only exactly once: when we implemented printing support in an iOS application with which needed to be compatible with both OS 3.2 and 4.0. You need to subclass a particular class, but the class isn't available in 3.2. So you sort of have to subclass at runtime (though the conceptually neater way would be to use a normal subclass, put that into a framework and weak link, but Apple's iOS SDK terms allow static libraries only, so...).
Following Daniel's suggestion, you can implement a method in an NSObject
category of the form
[anObject overrideMethod:@selector(foo:)
byBlock:^(id self,id super,id originalArg){
...
}];
What you need to do is to
objc_allocateClassPair
againstself
's own class, to create a new temporary class- Turn a block into a function pointer, using e.g. this or this
method_setImplementation
to set the new implementation to the temporary class- use
object_setClass
toself
to set the class to the new temporary class - I haven't figured out how to provide
super
to the block :p
It's believed this is basically how the KVO is done by Apple, see e.g. this discussion.
Read Runtime reference.
What you have there in Java is an anonymous subclass. This is not possible in Objective-C (well, it sort of is but you would have to do some pretty involved contortions with the Obj-C runtime library).
But Objective-C as of iOS 4 or OS X 10.6 has "blocks", which is what the ^{}
syntax is for. This is Objective-C's notion of a closure. This isn't going to help you directly if the APIs that you're calling don't support block callbacks, but you may be able to create wrapper classes that use blocks instead of subclassed methods to handle callbacks.
There are many resources for learning about blocks in Objective-C.
精彩评论