0. Runloop

You can search Runloop on Youku and share runloop by Sunyuan @sunnyxx in iOS offline. With sun Yuan’s in-depth understanding of Runloop on his blog, you can go to Git or other places to find some cases for practice. The videos on Youku are the focus. Many explanations of Runloop on the web are more or less flawed.

This article mainly from the practical point of view, entry point analysis, do not memorize. For example, what is the content of the msgSend file printed by the Runtime message, and why object_setClass and method_setImplementation are two different methods; When dynamic method resolution is used and when messages are sent message forwarding.

  • Message sending mechanism: a process that uses a selector at run time to quickly find an IMP.
  • Message forwarding mechanism: IMP can not find the time, through some methods to do forwarding processing

The runtime application reference: www.jianshu.com/p/6bcff1f9f…

It is strongly recommended that learned to read it again after English source: developer.apple.com/library/arc…

1. Basic knowledge of Runtime 2. Low-level call process of OC method 3. Message sending 4. Dynamic method resolution 5. Message forwarding 6Copy the code

1. Runtime basics

Current version: iPhone programs and 64-bit programs in Mac OS X V10.5 and later interact with runtime systems:

The general process of program execution: code –> compile link –> execute

C, the program is compiled into what, run what call

Oc language, dynamic language, what the program is compiled into, the program can be dynamically changed during running (dynamically changing method calls, dynamically adding methods)

The code can be found at github.com/tanghaitao/…

2. Call the underlying process of OC method

Using the clang compiler, execute the command clang-rewrite-objc main.m on the terminal and drag the main. CPP file into the project. Otherwise it will participate in compiling sources specific code at github.com/tanghaitao/…

objc_msgSend(p, sel_registerName("walk"));
Copy the code
NSLog(@"%p %p",@selector(walk),sel_registerName("walk"));
//0x100003fa2 0x100003fa2
Copy the code

It can be concluded from the above:

The oc method call is actually a call to the objc_msgSend function. Message receiver The execution of the message name objc_msgSend can be roughly divided into three parts 1. Message sending 2. Dynamic method resolution 3. Message forwardingCopy the code

2.1 Message Sending

Below I will combine objC source github.com/tanghaitao/… A detailed analysis of the objc_msgSend message sending layer:

Objc source code is mainly composed of assembly C ++.

As shown above: Search objc_msgSend for objC-msG-arm64. s assembler. ENTRY _objc_msgSend indicates ENTRY x0 message receiver message name. Compare nil check and tagged Pointer Check. Returns if there is no message receiver. We then look for x13 =isa(where isa is not just a pointer, but an and operation) and find the class. Class cache, CacheLookup Normal

If one is found (i.e., a Hit), it is found in the cache, CacheHit, as shown below:

Imp is called directly in the cache

If not found (i.e. CheckMiss), __objc_msgSend_uncached

Get cached ___objc_msgSend_uncached, and get cached _entry __objc_msgSend_uncached from the MethodTableLookup method list

Then call __class_lookupMethodAndLoadCache3, can’t find the search after the search, because from assembly into c, less can only search with an underscore.

The underlying principle of objc_msgSend is analyzed in detail through source code. The following is a summary:

2.2 Dynamic method analysis

If the IMP is not found in the class’s cache and method list, or in the parent class’s cache and method list, a dynamic method resolution is performed, then goto Retry, and a second lookup is performed from the class’s cache and method list, and the parent class’s cache and method list.

The dynamic method analysis process is shown as follows:

If it is not a metaclass, the instance method _class_resolveInstanceMethod is called

If it is a metaclass, the class method _class_resolveClassMethod is called

Simple look at the source code is too boring, the following combined with specific examples to explain: specific code at github.com/tanghaitao/…

I made a brief summary of instance objects, class objects, and metaclass objects, as follows:

[p], object_getClass(" class name ")== equivalent to if(p) p->getIsa() // isa finds the class, isa finds the metaclass, and is finds the root metaclass. // Instance objects hold special instance methods. The [p method0] // class object stores methods for all special instances - the minus sign [P1 method0] [P2 method0] [p3 method0] // metaclass object stores all class methods. + Person method1;Copy the code

Dynamic method parsing: instance method C method and oc method specific code at github.com/tanghaitao/…

Dynamic method resolution of class methods: detailed code at github.com/tanghaitao/…

2.3 Message Forwarding

If message imp and dynamic method parsing are not found, message forwarding _objc_msgForward_impcache is entered

Message forwarding source code is not exposed in objC source code, you need to print out the specific message forwarding process through THE API,(of course, you can also use shell breaking, hopper and other tools reverse derived, personal not recommended) : specific code at github.com/tanghaitao/…

extern void instrumentObjcMessageSends(BOOL);

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

The printed result is output to the /private/ TMP/msgsend-xxx file. To find the msgsend-xxx file, go to the end of /private/ TMP and run xcode project.

(void)walk, [[Person new] walk]; After running, there is no IMP, nor dynamic resolve, and the message forwarding process is entered

msgdoc-xxx

The message forwarding code of the class method can be found at github.com/tanghaitao/…

The difference between instance methods and class methods in message forwarding: Instance methods can only be forwarded to instance methods. Class methods can be forwarded to instance methods and class methodsCopy the code

3. The API application

The main code for the Runtime API: github.com/tanghaitao/…

Example code at github.com/tanghaitao/…

It is suggested that we run about, more basic, do not feel difficult, in fact, is some API calls.

3.1 Application of class

Let’s take a look at objc_class’s source code

class_rw_tCan be saidRead and write.Indicates that the objc_registerClassPair class can be added before and after registration.class_ro_tsaidRead only read onlySaid,Only in the Objc_registerClassPair before class registrationIvars is a class_ro_t struct and is read-only. It is not possible to add an instance variable directly after class registration.

3.2 Application of the method

Tableview Settings, page statistics, MLeakFinder, array out-of-bounds protection, and more.

3.3 Application of attribute variables

See case github.com/tanghaitao/… A thousand words are omitted here