Hi 👋
- 📚 Personal site: lab.lawliet
- 📦 Technical documentation
- 🐙 making
- Wechat: RyukieW
My apps
– | Mine Elic endless sky ladder | Dream of books |
---|---|---|
type | The game | financial |
AppStore | Elic | Umemi |
Think about it. What does the following code output?
BOOL result1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL result2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL result3 = [[RYModel class] isKindOfClass:[RYModel class]];
BOOL result4 = [[RYModel class] isMemberOfClass:[RYModel class]];
NSLog(@"Class\n %hhd \n %hhd \n %hhd \n %hhd", result1, result2, result3, result4);
BOOL result5 = [[NSObject alloc] isKindOfClass:[NSObject class]];
BOOL result6 = [[NSObject alloc] isMemberOfClass:[NSObject class]];
BOOL result7 = [[RYModel alloc] isKindOfClass:[RYModel class]];
BOOL result8 = [[RYModel alloc] isMemberOfClass:[RYModel class]];
NSLog(@"Instacne\n %hhd \n %hhd \n %hhd \n %hhd", result5, result6, result7, result8);
Copy the code
Results:
Class
1
0
0
0
Instacne
1
1
1
1
Copy the code
If you take the code literally, your answer should be different. We from the source layer to understand it, the source code is not long, very easy to understand.
A, isKindOfClass
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = self->ISA(a); tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {
if (tcls == cls) return YES;
}
return NO;
}
Copy the code
1.1 Flowchart -Class
- The [NSObject class]
RootClass
RootClass
-(ISA)>RootMetaClass
-(superClass)>RootClass
- true
- [RYModel class]
[RYModel class]
-(ISA)>RYModelMetaClass
-(superClass)>RootMetaClass
-(superClass)>RootClass
-(superClass)>nil
- false
1.2 Flowchart-Instance
- NSObjectInstance
NSObjectInstance
-(class)>RootClass
- true
- RYModelInstance
RYModelInstance
-(class)>RYModelClass
- true
Second, the isMemberOfClass
+ (BOOL)isMemberOfClass:(Class)cls {
return self->ISA() == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
Copy the code
So that’s pretty simple, so I won’t go into it.
You think this is the end?
If you look at this and you think it’s okay? That’s a problem…
We run OC source code, two breakpoints.
+/- (Bool)isKindOfClass:(Class) CLS
3.1 the assembly
Through breakpoint assembly, we found the instruction objc_opt_isKindOfClass where we called isKindOfClass
-> 0x10000381c <+332>: mov rdi, qword ptr [rip + 0x4f7d]; (void *)0x0000000100008808: RYModel
0x100003823 <+339>: call 0x100003b42 ; symbol stub for: objc_opt_class
0x100003828 <+344>: mov rbx, rax
0x10000382b <+347>: mov rdi, qword ptr [rip + 0x4f6e]; (void *)0x0000000100008808: RYModel
0x100003832 <+354>: call 0x100003b42 ; symbol stub for: objc_opt_class
0x100003837 <+359>: mov rdi, rbx
0x10000383a <+362>: mov rsi, rax
0x10000383d <+365>: call 0x100003b48 ; symbol stub for: objc_opt_isKindOfClass
Copy the code
3.2 objc_opt_isKindOfClass
// Calls [obj isKindOfClass]
BOOL
objc_opt_isKindOfClass(id obj, Class otherClass)
{
#if __OBJC2__
/ / found empty
if (slowpath(! obj))return NO;
Class cls = obj->getIsa(a);if (fastpath(! cls->hasCustomCore())) {
for (Class tcls = cls; tcls; tcls = tcls->getSuperclass()) {
if (tcls == otherClass) return YES;
}
return NO;
}
#endif
// This can be ignored
return ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}
Copy the code
And when we break here, we find that we do enter here. And the Class and Instance methods go here.
The compiler optimizes this by replacing it with the more efficient objc_opt_isKindOfClass.
Added: slowpath & Fastpath
These two macro definitions are often encountered during daily reading of OC source code. What does it mean?
// X is likely to be true, and fastPath can be abbreviated to truth judgment
#define fastpath(x) (__builtin_expect(bool(x), 1))
// slowpath is likely to be false
#define slowpath(x) (__builtin_expect(bool(x), 0))
Copy the code
The __builtin_expect directive was introduced by GCC
- Purpose: The compiler can optimize code to reduce performance degradation caused by instruction jumps. Performance optimization
- What it does: allows the programmer to tell the compiler which branches are most likely to execute.
- The instruction is written as follows:
__builtin_expect(EXP, N)
. So the probability that e to the EXP is equal to N is high. fastpath
In the definition__builtin_expect((x),1)
It means that x is more likely to be true; That is, there is a greater chance of executing the if statementslowpath
Definition of the__builtin_expect((x),0)
That means it’s more likely that the value of x is false. You have a better chance of executing the else statement- In daily development, you can also optimize the compiler to achieve performance optimization by setting the path as follows:
Build Setting
–>Optimization Level
–>Debug
–>Change "None" to "fastest" or "smallest"