We all know that OC is a dynamic language, is the runtime, how to reflect his dynamic, today with the SEL analysis, before sharing the hooks can be seen in fact, and now specifically see how OC is found through the SEL function.
[Self Performselector: @selector (ABCD)]; [Self ABCD]; This method may be compiled without passing
If we do not write ADCD method inside the class method, so it will collapse, OC is how to do it
After the method is called, OC emits a objc_msgsend, passing the message to the original to find out if the SEL in this class exists method
Suppose that this class does not exist will find out whether there is a classification in the project provides this method
If there is no such method in the classification, the system forwards the message to its parent class, and the parent receives the message and then executes the above operation, finds the method, and then forwards the message.
Assuming that the final message is not found, it will be executed with the last messages forwarding (msg forwarding) operation
If the forwarding out of no one to receive, NSObject in the Doesnotrecognizeselector chose to throw an exception, which is what we see crash
The process is a little complicated, and you'll think it's slow, the first time it's really slow, and the sex Objc_msgsend will write the matching results to the map cache, and each class has such a piece of cache.
The whole process is the one above, let's talk about the 4th message forwarding how to deal with it:
Message forwarding also has two phases:
1. Dynamic method parsing: means asking the recipient to add a method to implement the function
+ (BOOL) Resolveinstancemethod: (SEL) Selecotor//object method + (BOOL) Resolveclassmethod: (SEL) SEL//class method
A method can be dynamically added to a class in a method.
- (void) viewdidload { [super viewdidload]; // Do any additional setup after loading the view, typically From a nib. [self performselector: @selector (ABCD )];} + (BOOL) Resolveinstancemethod: (SEL) sel { nsstring *selname = Nsstringfromselector (SEL); if ([selname isequaltostring:@ "ABCD"]) { class_addmethod (Self, sel, class_ Getmethodimplementation ([self class], @selector (Oklala)), method_gettypeencoding (Class_ Getinstancemethod ([self class], @selector (Oklala))); return YES; } return [super Resolveinstancemethod:sel];} - (void) Oklala { &nbsP; nslog (@ "Oklala");}
2. Complete message forwarding: see if there are any other objects to deal with, there is a turn out, no words encapsulated into Nsinvocation object handling
1) If it can be transferred to another object for processing:
-(ID) Forwardingtargetforselector: (SEL) Aselector
You can return the object you want to forward.
@interface abcdcaller:nsobject@end@implementation abcdcaller-(void) ABCD {NSLog (@ "~~~~~~");} @end @implementation viewcontroller-(void) viewdidload {[Super viewdidload]; Additional setup after loading the view, typically from a nib. [Self Performselector: @selector (ABCD)];} -(ID) Forwardingtargetforselector: (SEL) Aselector {NSLog (@ "!!!!!!!!!!!!!"); return [[Abcdcaller alloc] init];} @end
2) If no object can be forwarded (full message forwarding)
-(void) Forwardinvocation: (nsinvocation *) aninvocation
The opportunity to finally handle the message
Assuming that your message forwarding is not handled, then the 5th step to catch the exception, it will not rush to collapse
@try {[Self performselector: @selector (ABCD)]; } @catch (NSException *exception) {NSLog (@ "~~~~~~~~"); } @finally {}
The runtime process for @selector in iOS