This is the 5th day of my participation in the August More Text Challenge
First take a look at apple WWDC2020 video on runtime optimization
One, memory – likero
data
The last chapter looked at class properties and methods, but what about member variables?Through printclass_rw_t
theproperties()
Finding only class attributes but no member variables, we passWWDC2020 about Runtime optimizationThe video explains thatMember variables
inro
In the. whileclass_rw_t
And you can see that in the structurero
theget
methods
printclass_rw_t
In thero
And got aclass_ro_t
.class_ro_t
You can see that there is aivars
Property, print it out and you get oneivar_list_t
Then through theThe get method
You can find all of themMember variables
Member variables and attributes and encoding
Member variables and attributes
We found member variables in the previous section. How are member variables and attributes represented underneath?
throughclang
Commands are compiled to the underlying levelC++
fileYou can see that in the underlying C++ there are no attributes, but allLRPerson_IMPL
Structure, and properties are converted to bands_
Form.At the same time, properties in OC are generated in the underlying C++get
andset
Method, while member variables do not
2, coding
In C++ source code, you can see these symbols. What are these symbols? What does the stand for mean?
These are all codes that can pass throughcommand + shift + 0
Search,ivar_getTypeEncoding
, click on theType Encodings
View detailed memory. The enclosedType Encodings addresses
For example, “setName:”, “v24@0:8@16” Said void 2, a total of 24 function parameters in the memory size 3 and @ the first parameter (hidden) parameters namely self 4, 0 start from 0 # 5, : the second parameter (hidden) parameters SEL 6, 8 from 8 position 7, @ the third parameter 8, 16, starting from the 16th position
3, add
Instance variables: Special member variables (object type declaration, instantiation of a class), non-basic data classes
Three,setter
,getter
The underlying principles of the method
1.A setter method
In the underlying C++ file just compiled, you can see the properties in OCget
andset
Methods. But a closer look revealsnickName
theset
And the way to do that is byobjc_setProperty
To achieve, whilename
andaname
theset
The method is implemented by memory translation assignment
fromllvm
Look in the source codeobjc_setProperty
, found ingetSetPropertyFn
Created in theKeep lookinggetSetPropertyFn
Keep lookingGetPropertySetFunction
foundGetPropertySetFunction
The call is in aswitch
thecase
Medium, checkPropertyImplStrategy
type PropertyImplStrategy
The implementation of theYou can see it hereIsCopy
If it isIsAtomic
The assignment isGetSetProperty
Otherwise, forSetPropertyAndExpressionGet
, socopy
Is to affect useobjc_setProperty
Important factors, through the following code to verify
@property (nonatomic.copy) NSString *nickName;
@property (atomic, copy) NSString *nickName1;
@property (nonatomic) NSString *nickName2;
@property (atomic) NSString *nickName3;
Copy the code
withclang
Command compiled intoC++
Source code can be found withcopy
Modifies the attributes underlying the passobjc_setProperty
implementationset
Method, and others via memory translation assignment
inobjc
Look at the source codeobjc_setProperty
Function implementation You can see the underlying callcopyWithZone
. socopy
Modifier properties copy memory, other modifiers do not copy memory translation
2,getter
methods
In the inquiryset
Method, we can see someget
Methods byobjc_getProperty
Implementation, while some are directreturn
A memory shifted value 在llvm
Continue to exploreobjc_getProperty
.PropertyImplStrategy
A type ofGetSetProperty
ultimatelygetter
The determining factor for the method is this codeThis code is also clearly commented
- If it is
copy
Modified property, used withsetProperty
- If the property is still used
atomic
Embellish, then usegetProperty
Class method storage API way parsing
There are two methods in a class
- (void)sayHello;
+ (void)sayHappy;
Copy the code
1.class_getInstanceMethod
void lrInstanceMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getInstanceMethod(pClass, @selector(sayHello));
Method method2 = class_getInstanceMethod(metaClass, @selector(sayHello));
Method method3 = class_getInstanceMethod(pClass, @selector(sayHappy));
Method method4 = class_getInstanceMethod(metaClass, @selector(sayHappy));
NSLog(@"%p - %p - %p - %p",method1,method2,method3,method4);
}
Copy the code
Output result:
0x1000081c0 - 0x0 - 0x0 - 0x100008158
Copy the code
Results analysis:
sayHello
Object methods exist in classessayHappy
Class methods exist in metaclasses
2,class_getClassMethod
void lrClassMethod_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method1 = class_getClassMethod(pClass, @selector(sayHello));
Method method2 = class_getClassMethod(metaClass, @selector(sayHello));
Method method3 = class_getClassMethod(pClass, @selector(sayHappy));
Method method4 = class_getClassMethod(metaClass, @selector(sayHappy));
NSLog(@"%p - %p - %p - %p",method1,method2,method3,method4);
}
Copy the code
Output result:
0x0 - 0x0 - 0x100008158 - 0x100008158
Copy the code
class_getClassMethod
Is to obtainClass method
And, at the bottom level, getObject methods of metaclasses
method4
The incoming isThe metaclass
, the underlying code will determine if it is already a metaclassDirect return
Otherwise return the metaclass An object is an instance of a class, a class is an instance of a metaclass, and there are no class methods at the bottom, only object methods
3,class_getMethodImplementation
void lrIMP_classToMetaclass(Class pClass){
const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
IMP imp1 = class_getMethodImplementation(pClass, @selector(sayHello));
IMP imp2 = class_getMethodImplementation(metaClass, @selector(sayHello));
IMP imp3 = class_getMethodImplementation(pClass, @selector(sayHappy));
IMP imp4 = class_getMethodImplementation(metaClass, @selector(sayHappy));
NSLog(@"%p - %p - %p - %p",imp1,imp2,imp3,imp4);
}
Copy the code
Output result:
0x100003ae0 - 0x7fff6e3b7580 - 0x7fff6e3b7580 - 0x100003b20
Copy the code
According to theclass_getInstanceMethod
Analysis of, hereimp2
imp3
There should be no implementation, but the output should have value. This involves the method lookup process, which returns one even if none is found_objc_msgForward
. More on the message forwarding mechanism later
4,isKindOfClass
,isMemberOfClass
void kindOfTest(void) {
BOOL re1 = [(id) [NSObject class] isKindOfClass:[NSObject class]].BOOL re2 = [(id) [NSObject class] isMemberOfClass:[NSObject class]].BOOL re3 = [(id)[LRPerson class] isKindOfClass:[LRPerson class]].BOOL re4 = [(id)[LRPerson class] isMemberOfClass:[LRPerson class]].NSLog(@" re1 :%d\n re2 :%d\n re3 :%d\n re4 :%d\n",re1,re2,re3,re4);
BOOL re5 = [(id) [NSObject alloc] isKindOfClass:[NSObject class]].BOOL re6 = [(id) [NSObject alloc] isMemberOfClass:[NSObject class]].BOOL re7 = [(id)[LRPerson alloc] isKindOfClass:[LRPerson class]].BOOL re8 = [(id)[LRPerson alloc] isMemberOfClass:[LRPerson class]].NSLog(@" re5 :%d\n re6 :%d\n re7 :%d\n re8 :%d\n",re5,re6,re7,re8);
}
Copy the code
Output result:
re1 :1
re2 :0
re3 :0
re4 :0
re5 :1
re6 :1
re7 :1
re8 :1
Copy the code
According to theisKindOfClass
,isMemberOfClass
Source code analysis:
-
+ (BOOL)isKindOfClass:(Class) CLS Class method. Get the metaclass of the class, judge whether the metaclass and parameter are the same, if not, cycle to judge the parent class. In RE1, NSObject is the root class, and the parent class of the root metaclass is the same as the argument, return YES. In RE3 you go from the LRPerson metaclass to the parent class NSObject to nil, which is different from the argument LRPerson class. So return NO.
-
– (BOOL)isKindOfClass:(Class) CLS object method. Get the class of the current object, judge whether the class and parameter are the same, if not, loop to judge the parent class. The NSObject object in RE5 has the same class as the parameter NSObject, returning YES. The LRPerson object in RE7 has the same class as the parameter LRPerson class and returns YES.
-
+ (BOOL)isMemberOfClass:(Class) CLS Class method. Get the metaclass of the class, check whether the metaclass and argument are the same, and return NO. The LRPerson metaclass in RE4 is not the same as the LRPerson class and returns NO.
-
– (BOOL)isMemberOfClass:(Class) CLS object method. Gets the class of the object, determines whether the class and argument are the same, and returns YES for NSObject. The LRPerson class in RE8 is the same as the LRPerson class and returns YES.
It can also be found through compilationisKindOfClass
,isMemberOfClass
In the bottom, we goobjc_opt_isKindOfClass