This exploration stems from a question asked by a friend. When we define an instance variable of a class, we can specify its modifier:
This allows ivar (instance variable) to be correctly reference counted under ARC just like properties. So the question is, if this class is dynamically generated:
How do you add property modifiers to ivar like above? After some investigation, I found that the modification information of ivar is stored in the Ivar Layout of Class:
ivarLayout and weakIvarLayout respectively record which ivars are strong or weak. What is not recorded are the basic types and __unsafe_unretained object types. These two values can be accessed through several APIs provided by the runtime:
But we are unlikely to use these APIs. The value of IvarLayout is determined by the runtime, so there is no need to care about its existence. However, in order to solve the above problems, we tried to crack the encoding method of IvarLayout. For example, if the class is defined as:
The value of ivarLayout storing strong ivar is 0x012000 The value of weakIvarLayout that stores weak ivar is 0x1200 A uint8_t is two digits in hexadecimal, so the encoded value is a pair of two digits. Take the above ivarLayout as an example: The first two digits 01 indicate that there are 0 non-strong objects and 1 strong object. The next two digits 20 indicate that there are 2 non-strong objects and 0 strong objects. ***The two 00s are the end character, just like the \0 in cstring Similarly, the weakIvarLayout above: The first two digits 12 indicate that there is 1 non-weak object and the next 2 consecutive weak objects. 00 End character In this way, two layout code values can be used to check whether an ivar is strong or weak. If neither is found, it means that the object is unsafe_unretained. As an exercise, if the class is defined as:
The value of ivarLayout storing strong ivar is 0x012100 The value of weakIvarLayout that stores weak ivar is 0x01211000
I thought I had solved this problem, but the runtime continued to slap me in the face, and the strong and weak memory management did not take effect. I continued to study and found that there is a flag in the class flags to record whether the class is ARC. When the class is compiled normally and marked with the -fobjc-arc flag, this flag is 1, but the dynamically created class does not set it. So I can only continue to use black magic to set this flag at runtime. I will not go into details about the exploration process. The implementation is as follows:
After putting this fixup in objc_registerClassPair(class);, the dynamic class can finally operate ivar like the statically compiled class. You can test it:
Done. |
<<: 5 Best AngularJS Program Building Frameworks
>>: 4 memory usage issues game developers need to pay attention to
Changsha tea takeaway arrangement, tea service co...
If we do a questionnaire survey: Which planet in ...
One minute with the doctor, the postures are cons...
How to plan a screen-sweeping event? Just read th...
As user behavior undergoes tremendous changes in ...
Since the beginning of 2020, the World Economic F...
[[140622]] July 15, 2017 - Over the past decade, ...
On August 3, Tesla announced its second quarter f...
The iMac may be a truck, but Apple is making sure...
Currently, Alipay is one of the most mainstream m...
The mini program provides convenience for publici...
Have you ever noticed those ocean-going cargo shi...
Tik Tok has been popular for a while now, and has...
Mixed Knowledge Specially designed to cure confus...
When you encounter any marketing problem, your ma...