What is it like to create a serial-oc object
What is the flow of series -OC method call
Simple understanding of series-class and meta-class structures
Introduction: Through some simple understanding of OC object, class object, metaclass object structure, method call process, we can more easily understand the message mechanism of the sending message stage is how to search method.
OC message mechanism
- Method calls in OC are different from function calls in other languages (address passing calls to functions) by message mechanism. All method calls are made at Runtime through the objc_msgsend function.
For example, [person eatWithFood:@[@”rice”,@”fruits”]].
The system sends an eatWithFood message to the person object.
Have Person find the corresponding method implementation and execute its code.
- The system calls
objc_msgSend(id self, SEL, cmd, ...)
- Will take person as the first argument to the function and call it the “receiver” of the message
- The eatWithFood method is going to be the second argument, which is called the selector.
- The arguments to the eatWithFood method are passed in order as arguments to the objc_msgSend function
- Objc_msgSend is executed in three low-level phases:
- Message sending (find method in current class object, parent class object)
- Dynamic method parsing
- forward
Message is sent
- First, look for the corresponding method in the recipient’s class. If not, look up the inheritance system, find the method and jump to the code implementation.
//class -> super class ->... Meta -> super meta- > root -> root -> root -> root -> root -> root -> root -> root -> root -> root -> root -> root -> root -> root -> root meta-class -> root classCopy the code
Method to find specific steps |
---|
1. Method caching in classcache Find, there is a call, no in this classclass_rw_t Find, call, and will cache the method tocache To facilitate the next search. |
2. If no method is found, the same operation is repeated in the parent class. Whenever the method is found, the method will be called and cached in the parent classcache In the. |
3. If yes, no further action is requiredMessage is sentAnd still didn’t find a way to enterDynamic method parsingPhase. |
Dynamic method parsing:
- After the message is sent and no method is found, the Runtime asks the receiver if a method can be added dynamically to handle the current selector. This phase is called “dynamic method resolution.”
1. An object calls a class method when it receives an undecipherable message
+ (BOOL)resolveInstanceMethod:(SEL) SEL SEL: selectors, methods not foundCopy the code
Indicates asking if a new method can be added to handle the selector.
2. The add method can be used
class_addMethod(Class _Nullable __unsafe_unretained cls, SEL _Nonnull name, IMP _Nonnull imp, Const char * _Nullable types) const char * _Nullable types) const char * _Nullable types) const char * _Nullable types) Types stands for Type EncodingCopy the code
- Example:
//- (void)eatWithFood:(NSArray *)foods{ // NSLog(@"I eated %@ for lunch",foods); //} #pragma mark - method_t is a low level structure, which is not exposed and cannot be used directly. char *types; IMP imp; }; + (BOOL)resolveInstanceMethod:(SEL)sel{ if (@selector(eatWithFood:) == sel) { //1. // struct method_t *newMethod = (struct method_t *)class_getInstanceMethod(self, @selector(eatLuch:)); // // // newMethod // class_addMethod(self, sel, newMethod->imp, newMethod->types); Method = class_getInstanceMethod(self, @selector(eatLuch:)); // // class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method)); Imp imp = class_getMethodImplementation(self, @selector(eatLuch:)); Method method = class_getInstanceMethod(self, @selector(eatLuch:)); const char *types = method_getTypeEncoding(method); class_addMethod(self, sel, imp, types); return YES; } return [super resolveInstanceMethod:sel]; } // add method implementation - (void)eatLuch:(NSArray *)foods{NSLog(@" lunch %@", foods); }Copy the code
- C language function implementations can also be added
+ (BOOL)resolveInstanceMethod:(SEL)sel{ if (sel == @selector(eatWithFood:)) { class_addMethod(self, sel, (IMP)eatSomeFoods, "v24@0:8@16"); } return [super resolveInstanceMethod:sel]; } void eatSomeFoods(id self, SEL _cmd, NSArray *foods){NSLog(@" eat lunch --%@",foods); }Copy the code
- The above dynamic method resolution is for object method examples. If it is a class method, call the following method
+ (BOOL)resolveClassMethod:(SEL)sel
Copy the code
- Class_addMethod has an argument called types which is Type Encoding. If not, check out apple’s official documentation.
Type Encoding (string Encoding)
forward
- If the message receiver does not allow methods to be added dynamically, the message forwarding phase is entered, which is also divided into two phases:
1. Check whether other objects process the method. If yes, the receiver forwards the message to the object.
2. If no other object handles the message, start the full message forwarding mechanism, and the Runtime encapsulates all the details of the message in the NSInvocation object, giving the receiver one last chance to process the data and manage the message.
Backup receiver
If the class is consulted that it cannot add methods dynamically, the receiver is asked to see if there are other classes to handle the selector, and if there is, the standby receiver.
The system calls the following methods to handle this step:
- (id) forwardingTargetForSelector aSelector: (SEL) as long as the return to a processing method of the objectCopy the code
Such as:
FRPerson.m
- (id) forwardingTargetForSelector aSelector: (SEL) {/ / direct returns a can handle the selector of the object, Then implement the method inside that object if (aSelector == @selector(eatWithFood:)) {return [[FRStudent alloc] init]; } return [super forwardingTargetForSelector:aSelector]; }Copy the code
FRStudent.m
#import "FRStudent. H "@implementation FRStudent - (void)eatWithFood (NSArray *)foods{NSLog(@" students eat %@ ",foods); } @endCopy the code
In this example, FRStudent processes the message, and the message forwarding stops there.
Complete message forwarding mechanism
- If no other receiver processes the message, the full message forwarding mechanism is entered
- All relevant information is encapsulated in the NSInvocation class
- Send to the target via the forwardInvocation method
- The system calls the following methods:
/ / return the method signature - (NSMethodSignature *) methodSignatureForSelector aSelector 1: (SEL). If the method signature returns nil, the last chance to process the method is abandoned, and error 2 is thrown. After the method signature is returned, the forwardInvocation method is firedCopy the code
// after the forwardInvocation is fired, anything can be done in this method implementation - (void)forwardInvocation:(NSInvocation *)anInvocationCopy the code
Such as:
/ / return the method signature - (NSMethodSignature *) methodSignatureForSelector (SEL) aSelector {if (aSelector = = @ the selector (eatWithFood:)) { return [NSMethodSignature signatureWithObjCTypes:"v24@0:8@16"]; } return nil; } / / methodSignatureForSelector method returns nil, The forwardInvocation is not called - (void)forwardInvocation:(NSInvocation *)anInvocation{if (anInvocation. Selector == @selector(eatWithFood:)) { //1. // [anInvocation invokeWithTarget:[[NSClassFromString(@"FRStudent") alloc] init]]; // // [anInvocation invokeWithTarget:[[NSClassFromString(@"FRCat") alloc] init]]; // Invocation target = NSClassFromString(@frstudent); // Invocation target = NSClassFromString(@"FRStudent"); // [anInvocation invoke]; //3. Once you get to the method, you can leave the unimplemented method alone, do something else unrelated to the method, or do nothing at all}}Copy the code
- Note: The three methods that enter the method forward phase all have class method types that handle calling class methods.
+ (id)forwardingTargetForSelector:(SEL)aSelector
Copy the code
+ (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
Copy the code
+ (void)forwardInvocation:(NSInvocation *)anInvocation
Copy the code
If Xcode doesn’t prompt you, you can just type out the object method and change the “-” to “+”.
How is series – KVO&KVC realized
On the structure and loading time of series-classification
Brief introduction to series-load and initialize call timing and practical use
How does serial-block work