Runtime is a set of apis available in two versions: Legacy Version. One of the early versions of Objective-C 1.0 32-bit Mac OSX was the Modern Version. The current version of the iPhone program and Mac OS X V10.5 after 64 OS

Objective-c programs have three ways to interact with the runtime system

  1. Through objective-C source code
  2. Through NSObject in the Foundation framework
  3. By calling the API interface provided to us by the runtime system

Object methods and class methods

   Person *p = [[Person alloc] init];
   [p run];
Copy the code

The clang analysis terminal command clang-rewrite-objc main.m -o main.cpp

typedef struct objc_object Person; typedef struct {} _objc_exc_Person; int main(int argc, const char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init")); ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("run")); / / (void (id, SEL)) (*) (void *) objc_msgSend) (p (id). // sel_registerName("run") method number} return 0; }Copy the code

The Person is compiled into an objC_Object structure. The OC object is essentially a structure. The essence of any method call is that it is compiled into the objc_msgSend method

   objc_msgSend(p,sel_registerName("run"));
   NSLog(@"%p---%p",sel_registerName("run"),@selector(run));
// 0x7fff356b2cc2---0x7fff356b2cc2
Copy the code

• Class methods send messages

   objc_msgSend(objc_getClass("LGStudent"),sel_registerName("walk"));
Copy the code

• Send a message to the parent class (object method)

    struct objc_super cus;
    cus.receiver = p;
    cus.super_class = class_getSuperclass([p class]);
    objc_msgSendSuper(&cus, @selector(run));
Copy the code

• Send a message to the parent class (class method)

    struct objc_super cusSuper;
    cusSuper.receiver = [p class ];
    cusSuper.super_class = class_getSuperclass(objc_getClass([p class]));
    objc_msgSendSuper(&cusSuper, @selector(run));
Copy the code

Objc_getClass ([p class]): represents a metaclass

  1. Object methods exist on a class
  2. Class methods exist on metaclasses
  3. Objects and classes exist as instances on both classes and metaclasses, so object objects and instance methods exist as instance methods

Message lookup & forwarding

Assembly parts

• objc_msgSend • LNilOrTagged tagged Pointer Stores some simple data: NSNumber NSDadte if the pointer is less than or equal to LNilOrTagged, return. • LGetLsaDone isa is complete. • CacheLookup isa macro definition • objc_msgSend_uncached • CacheHit -> CALL • CheckMiss ->__objc_msgSend_uncached • 1 GETIMP-> LGetImpMiss • 2 NORMAL – > __objc_msgSend_uncached – > _class_lookupMethodAndLoadCache3 C function, 3 LOOKUP – > __objc_msgLookup_uncached • The add, MethodTableLookup, bl __class_lookupMethodAndLoadCache3

Message lookup & forwarding section

Dynamic method parsing

No implementation found. Try method resolver once. Only executed once • Object method _class_resolveInstanceMethod • Class method _class_resolveClassMethod

void _class_resolveMethod(Class cls, SEL sel, id inst) { if (! CLS - > isMetaClass ()) {/ / not a metaclass / / try/CLS resolveInstanceMethod: sel _class_resolveInstanceMethod (CLS, sel, inst); } else {/ / is a metaclass / / try [nonMetaClass resolveClassMethod: sel] / / and/CLS resolveInstanceMethod: sel _class_resolveClassMethod(cls, sel, inst); if (! lookUpImpOrNil(cls, sel, inst, NO/*initialize*/, YES/*cache*/, NO/*resolver*/)) { _class_resolveInstanceMethod(cls, sel, inst); }}}Copy the code

When we implement this method

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    NSLog(@"hellow");
return [super resolveInstanceMethod:sel];
}
Copy the code

It actually executed twice. Why is that

static void _class_resolveInstanceMethod(Class cls, SEL sel, id inst){
    BOOL (*msg)(Class, SEL, SEL) = (typeof(msg))objc_msgSend;
    bool resolved = msg(cls, SEL_resolveInstanceMethod, sel);
}
Copy the code

By default, the system sends a message once: a SEL_resolveInstanceMethod message is sent to the current class. One more note:

 Method hellowordM1= class_getClassMethod(self, hellowordSEL);
Method hellowordM= class_getInstanceMethod(object_getClass(self), hellowordSEL);
Copy the code

• Class methods exist on a metaclass • object methods exist on a class • all exist as power objects • Class methods and object methods of a metaclass are the same

Standard message forwarding process

_objc_msgForward_impcache through the source code can be found that only the assembly call not implemented, but we can through instrumentObjcMessageSends output system function calls

extern void instrumentObjcMessageSends(BOOL);
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        instrumentObjcMessageSends(YES);
        [LGPerson  walk];
        instrumentObjcMessageSends(NO);
    }
    return 0;
}
Copy the code

A msgfy-54285 file is found in ⁨Macintosh HD⁩ ▸ ⁨private⁩ ▸ ⁨ TMP ⁩Here you can see the flow of message forwarding: , resolveInstanceMethod, forwardingTargetForSelector, methodSignatureForSelector, forwardInvocation, DoesNotRecognizeSelector Actual application scenarios: • Custom event handling. Crash phone call stack information, save sandbox, upload server • AOP cut into. Aspect • Array out-of-bounds handling • message forwarding.. • Runtime dynamic creation of some controllers, etc., pages that need to be hidden

[demo](