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:
- Exploring the underlying principles of iOS alloc
- Exploration of the underlying principles of iOS structure in vivo alignment
- The nature of the object explored by iOS underlying principles & the underlying implementation of ISA
- The underlying principles of the ISA-class (part 1)
- 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 memory
Memory that does not change after loading. (Class_ro_t belongs to clean memory because it is read-only)dirty memory
Memory 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 memory
thanclean memory
Much more expensive. It must exist for as long as the process is running. On the other hand, can be excludedclean memory
To make room for something else, because the system can always reload it from disk if you need it. MacOS exchangedirty memory
Options, butdirty memory
It’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_t
Was halved in size
cache_t
的 insert()
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;
- for
t1
In terms ofNSObject class
的isa
是NSObject MateClass
.NSObject MateClass
的superClass
是NSObject class
So, return YES; - for
t2
In terms ofSMPerson class
的isa
是SMPerson Mateclass
That is not the same asSMPerson class
.SMPerson Mateclass
的superclass
是NSObject MateClass
That is not the same asSMPerson class
, so return NO; - for
t3
In terms ofNSObject class
的isa
是NSObject MateClass
That is not the same asNSObject class
, so return NO; - for
t4
In terms ofSMPerson class
的isa
是SMPerson MateClass
That is not the same asSMPerson class
, so return NO. - for
t5
In terms ofobjc
的isa
是NSObject class
Is equal toNSObject class
, so YES; - for
t6
In terms ofobjc
的isa
是SMPerson class
, so return YES; - for
t7
In terms ofobjc
的isa
是NSObjcet class
, so return YES; - for
t8
In terms ofobjc
的isa
是SMPersn 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.