Write in the front: the exploration of the underlying principles of iOS is my usual development and learning in the continuous accumulation of a step forward road. I hope it will be helpful for readers to record my journey of discovery.Copy the code

The directory is as follows:

  1. Exploring the underlying principles of iOS alloc
  2. Exploration of the underlying principles of iOS structure in vivo alignment
  3. The nature of the object explored by iOS underlying principles & the underlying implementation of ISA
  4. The underlying principles of the ISA-class (part 1)
  5. The underlying principles of the ISA class (middle)

Summary column for the above

  • Summary of the phase of iOS underlying principle exploration

Writing in the front

In the previous series of articles, we started with alloc, the most used and basic in development, and explored the underlying process and memory knowledge of the underlying structure of the class. Then we explored the nature of the object and the underlying implementation of its internal ISA. Further, we explored the bits and cache of the class.

Then, as the final content of the underlying principle structure of the class, I will summarize it from the whole.

To prepare

Changes made to the objective-c runtime from apple WWDC2020

Advances in the Objective-C runtime

Drill down into the microscopic world of low-level bits and bytes behind every Objective-C and Swift class. Learn how recent changes to internal data structures, method lists, and marker Pointers provide better performance and lower memory usage. We'll show you how to identify and fix code crashes that depend on internal details, and show you how to keep your code unaffected by runtime changes.Copy the code
  • clean memoryMemory that does not change after loading. (Class_ro_t belongs to clean memory because it is read-only)
  • dirty memoryMemory that changes while the process is running. (The class structure becomes dirty memory when used because the runtime writes new data to it, such as creating a new method cache and pointing to it from the class.)
  • dirty memorythanclean memoryMuch more expensive. It must exist for as long as the process is running. On the other hand, can be excludedclean memoryTo make room for something else, because the system can always reload it from disk if you need it. MacOS exchangedirty memoryOptions, butdirty memoryIt’s particularly expensive in iOS because it doesn’t use swapping.

class

Classes in the app binary on disk

It contains the most frequently accessed information: Pointers to metaclasses, superclasses, and method caches.

The structure of a class when it is first added from disk to memory

It also has a pointer to more data that stores other information, called class_ro_t Ro for read only. This includes the name of the class and information about methods, protocols, and instance variables. The Swift class and the Objective-C class share this infrastructure, so each Swift class also has these data structures.

When the class is first used

When a class is used for the first time, the runtime allocates additional storage space for it. The storage allocated by this runtime is class_rw_T for reading/writing data. In this data structure, we store new information that is generated only at run time. When a category is loaded, it can add new methods to the class, and the programmer can add them dynamically using the runtime API. Since class_ro_t is read-only, we need to keep track of these in class_rw_t.

Class’s overall structure

Separate parts that are not normally used, so thatclass_rw_tWas halved in size

cache_tinsert()Timing of invocation

Through source breakpoint debugging, we can find in the stack information

log_and_fill_cache

lookUpImpOrForward

That’s what we’re going to explore in terms of the process of sending and forwarding and finding messages. Leave it to our later articles to explore.

supplement

  • The interview questions

Source code analysis

We can find the implementation of the method in the source code:Analysis shows:

  • The isKindOfClass method is to find the metaclass based on ISA, compare it, then find the metaclass’s parent class, compare it, and loop on, as long as isa can find the metaclass, compare it, and return YES if it can be compared once.

  • The isMemberOfClass method of a class is to see if its metaclass is equal to the class to be compared.

  • The isKindOfClass method of an instance object is to see if its class is the same as the argument passed in;

  • The isMemberOfClass method of an instance object is to see if its own class is equal to the class to be compared;

  1. fort1In terms ofNSObject classisaNSObject MateClass.NSObject MateClasssuperClassNSObject classSo, return YES;
  2. fort2In terms ofSMPerson classisaSMPerson MateclassThat is not the same asSMPerson class.SMPerson MateclasssuperclassNSObject MateClassThat is not the same asSMPerson class, so return NO;
  3. fort3In terms ofNSObject classisaNSObject MateClassThat is not the same asNSObject class, so return NO;
  4. fort4In terms ofSMPerson classisaSMPerson MateClassThat is not the same asSMPerson class, so return NO.
  5. fort5In terms ofobjcisaNSObject classIs equal toNSObject class, so YES;
  6. fort6In terms ofobjcisaSMPerson class, so return YES;
  7. fort7In terms ofobjcisaNSObjcet class, so return YES;
  8. fort8In terms ofobjcisaSMPersn class, so return YES.

The output is as follows, as we analyzed from the source code.

1-0-0-0-1-1-1-1Copy the code

LLDB debugging

Is it really as consistent as the process of our analysis? Next we start the LLDB debug validation process:

As shown in the figure above, as you can see, I’m going to expand the analysis with breakpoint code debugging: familiar debug workdfllow -> always show Disassembly,

The break point finds that the isMemberOfClass method has a break point and isKindOfClass has no break point.

(objc_opt_isKindOfClass) (objc_opt_isKindOfClass) (objc_opt_isKindOfClass)

The objc_opt_class method gets the class to which isa is referred as an argument. If isa points to a metaclass, it returns the object, otherwise the class isa points to. That is, an instance calls this method, returning the instance’s class object; Class calls this method to return itself;

Then look;

If CLS exists, see if CLS is equal to otherClass. If CLS exists, see if CLS is equal to otherClass. If CLS exists, see if CLS is equal to otherClass. NO is returned until NO matches are found.