message forwarding is an important feature of the OC Runtime, and the main task of the OBJECTIVE-C runtime is to be responsible for message distribution, which we develop " Unrecognized selector sent to instance xx ", the instance object does not implement the corresponding message, usually we only need to implement the method is not implemented. In general, we deal with a method, run-time look for matching selector and then execute, but sometimes just want to create a method at runtime, the message does not have a specific implementation, this time there will be a run-time error, according to the order of message forwarding we have three kinds of solutions.
Dynamic Method Processing
First, let's look at a simple example, define a message class, define a Responsemethod method, do not implement the method, call directly:
Message *msg=[[message Alloc]init]; [MSG Responsemethod];
The error message is as follows:
Terminating app due to uncaught exception ' nsinvalidargumentexception ', Reason: '-[message Responsemethod]: Unrecogni Zed Selector sent to instance 0X10011AD20 '
The override of a dynamic method has two methods that can be called:
+ (BOOL) Resolveclassmethod: (SEL) sel __osx_available_starting (__mac_10_5, __iphone_2_0); + (BOOL) Resolveinstancemethod: (SEL) sel __osx_available_starting (__mac_10_5, __iphone_2_0);
At this point we just need to rewrite +resolveInstanceMethod: the return Yes to resolve the error message, note that we need to add a new function through the Class_method method to replace the original sel:
+ (BOOL) Resolveinstancemethod: (SEL) sel{ NSLog (@ "flyelephant-http://www.cnblogs.com/xiaofeixiang/"); if ([email protected] (Responsemethod)) { Class_addmethod ([Self Class],sel, (IMP) dynamicmethodimp, "[Email Protected]: "); return YES; } return [Super Resolveclassmethod:sel];} + (BOOL) Resolveclassmethod: (SEL) sel{ return [Super Resolveclassmethod:sel];}
Functions that are executed dynamically:
void Dynamicmethodimp (id self, SEL _cmd) { NSLog (@ "developer--dynamicmethodimp--%@", Nsstringfromselector (_cmd)) ;}
Message Forwarding
If the above method does not rewrite or return no, then we have two options in order, the principle of the two choices is the same, the message has a corresponding target, we need to replace the corresponding target:
-(ID) Forwardingtargetforselector: (SEL) Aselector __osx_available_starting (__mac_10_5, __iphone_2_0);
The Forwardingtargetforselector return parameter is an object, and if the object is non-nil, non-self, the system will forward the running message to the object execution, otherwise a third solution will be executed.
-(ID) Forwardingtargetforselector: (SEL) aselector{ NSLog (@ "flyelephant-http://www.cnblogs.com/xiaofeixiang/" ); NSLog (@ "Forwardingtargetforselector"); if ([email protected] (Responsemethod)) { return developer; } return self;}
The second message is to send the message to another object, and if you want to modify the message, use -forwardInvocation: the runtime to package the message into nsinvocation and return it to you for processing. after the office finishes, call i nvokeWithTarget,但是如果是是调用-forwardInvocation是无法执行成功,在执行之前我们进行方法签名。
-(Nsmethodsignature *) Methodsignatureforselector: (SEL) aselector{ NSLog (@ "Methodsignatureforselector"); if ([Super Respondstoselector:aselector]) { return [Super Methodsignatureforselector:aselector]; } else{ return [developer Methodsignatureforselector:aselector]; } -(void) Forwardinvocation: (nsinvocation *) aninvocation{ NSLog (@ "forwardinvocation"); SEL sel=[aninvocation selector]; if ([developer Respondstoselector:sel]) { [aninvocation invokewithtarget:developer]; } else{ [Super Forwardinvocation:aninvocation];} }
About methods in the developer class:
@implementation developer-(void) responsemethod{ NSLog (@ "blog Park: flyelephant-http://www.cnblogs.com/xiaofeixiang/"); NSLog (@ "Developer----Responsemethod");} @end
Message forwarding is used in the Cocoa Agent (Proxies) and the response chain (Responder Chain). Nsproxy is a lightweight class that works by forwarding messages to another object. It is useful if you want to lazily load a property of object. Nsundomanager also works, but intercepts messages, then executes them, rather than forwarding them to other places.
The response chain is about how cocoa handles and sends events and behaviors to the corresponding object, usually we handle the keyboard text box event first Responder, and if the message is not processed, forwards to the next -nextResponder . Keep going until you find an object that can handle the message, or you can't find it, error.
iOS Development-Message forwarding