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
- Through objective-C source code
- Through NSObject in the Foundation framework
- 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
- Object methods exist on a class
- Class methods exist on metaclasses
- 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](