So i am looking into message forwarding and running some unit tests when i came across some scant resources including apple's very own brand of documentation of using forwardInvocation: which as far as i can tell requires methodSignatureForSelector: to work.
now i get the general idea that methodSignatureForSelector: is required to see if the object you are trying to forward the message to has the matching method name and parameters so it can then call forwardInvocation: my question is why in apples documentation it says to call the superclass's implementation of methodSignatureForSelector: like so...
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [surrogate methodSignatureForSelector:selector];
}
return signature;
}
to me this looks like it's saying "If none of the classes I have inherited from have a way to handle this method, check to see if surrogate object does."
The example apples give is the Warrior acting in stead of the Diplomat when it comes to the method of negotiating. Given this example I do not see why you would check to see if warrior or any of it's parents ever have the appropriate method signature to forward to. So this leads me to believe it is there for another reason, one which i can't think of, can someone give me an example or help clear up where i might be missing the point?
TL;DR
why would I need [super methodSignatureForSelector:selector];?
You are correct - the example tries to get the method signature from the superclass, and if it cannot, it asks the surrogate for one. In that whole Forwarding and Inheritance section, Apple is guiding you in how it intends you to use message forwarding - whether you choose to listen is up to you :)
To fully, explain, I will walk through the main portions of the documentation:
Implementing the forwarding of messages does not immediately affect the
respondsToSelectorandisKindOfClassmethods. if you forwardnegotiateto a surrogate, if you call[myWarrior respondsToSelector:negotiate]will returnNOif the method does not exist in the inheritance hierarchy.The keyword is probably - so Apple is giving you a recommendation. Apple is stating that if you want the myWarrior object to return
YESin my example above since you forwardnegotiateto a surrogate object, then you need to overwrite therespondsToSelectormethod. Now note though there are other methods besidesnegotiatethat you can call, potentially in the surrogate that you do not wish to returnYES. For example, the Diplomat class might have ahavePeaceCelebrationmethod. When the Warrior class gets sent this message, you might not have implemented the forwarding of the message to the Diplomat class (since Warriors do not have peace celebrations) and therefore you will want to returnNO.Moreover, the parent class might have a
chooseWeaponmethod not in the Warrior class. If you call[myWarrior respondsToSelector:chooseWeapon]you most definitely want to check if the superclass responds to it since the surrogate (being a Diplomat) does not.Lastly, it is possible that both the parent class and the surrogate respond to the selector. Apple seems to recommend that the parent class should win out - a Warrior is a Warrior first, and a Diplomat for some methods, only if you force it to be. How you end up implementing it though is up to you.
The keyword is should - again a recommendation. This was the statement right before the code you provided. This is identical reasoning to
respondsToSelector, and is saying that the object should be a good citizen. It may be possible for the Warrior class to handle some remote messages, but not others, and same for the Diplomat class. If you choose to always forward it to the surrogate, it might be confusing if messages are forwarded that Warrior's superclass can handle. Or worse, it might forward messages that Warrior's superclass can handle but the surrogate cannot - potentially resulting in exceptions.