定义一个Person类
@interface Person : NSObject
@property (nonatomic, strong) NSString *age;
- (void)test;
@end
@implementation Person
- (void)test{
NSLog(@"age = %@",self.age);
}
ViewController 继承自UIViewController
在ViewController 书写以下代码。问是否能编译通过,如果可以输出什么是什么?
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
id cls = [Person class];
void * temp = &cls;
[(__bridge id)temp test];
Person *per = [[Person alloc] init];
[per test];
}
运行结果
age = <ViewController: 0x7fb25241d9c0>
age = (null)
product -> Preform Action-> assemble 查看中间层代码
.loc 1 18 5 prologue_end ## /Users/iOS/Desktop/Demo/Demo/ViewController.m:18:5
movq -8(%rbp), %rsi
movq %rsi, -32(%rbp)
movq L_OBJC_CLASSLIST_SUP_REFS_$_(%rip), %rsi
movq %rsi, -24(%rbp)
movq L_OBJC_SELECTOR_REFERENCES_(%rip), %rsi
leaq -32(%rbp), %rdi
callq _objc_msgSendSuper2
其实super 底层实现的是_objc_msgSendSuper2
而不是上一篇文章的 _objc_msgSendSuper
两个还是有区别的。我们先看一下_objc_msgSendSuper
传参
// rewrite-objc 结果
_objc_msgSendSuper(
struct {
id self
Class superClass
},@selector(viewDidLoad)
)
// 底层实现 汇编结果
_objc_msgSendSuper2(
struct {
id receiver
Class current_class
},@selector(viewDidLoad)
)
通过assemble生成的中间代码可以看出调用的是_objc_msgSendSuper2
在源码中也有对_objc_msgSendSuper2
的参数介绍
ENTRY _objc_msgSendSuper2
UNWIND _objc_msgSendSuper2, NoFrame
ldp p0, p16, [x0] // p0 = real receiver, p16 = class
ldr p16, [x16, #SUPERCLASS] // p16 = class->superclass
CacheLookup NORMAL
END_ENTRY _objc_msgSendSuper2
从源码中 可以看到 传入参数为第一个为接收者(self) 第二个参数为 [current class]
ldr p16, [x16, #SUPERCLASS] // p16 = class->superclass
在上面这句代码中 获取到当前class 的superclass
我们先看图下面区域
蓝色区域为person的实例变量。per指向person实例变量
而我们的对象方法存储在class中,所以通过指针找到per ->isa -> class ->方法列表 ->具体方法
我们再看图上面区域
蓝色区域为cls变量 temp指向cls cls指向person class
从图中我们可以看出,两个在内存结构几乎一致。
我们知道 c中是通过地址与指针找到对象。可以触发person的对象方法
既然是地址寻找。那当我们调用age属性的时候,正常走的是person实例变量的地址。而在temp中,这个地址为
self,所以temp中调用的age为viewcontroller 因为他们在相同的内存位置。
+ (BOOL)isMemberOfClass:(Class)cls {
// 当类传进来的时候 获取的是mate-class
return object_getClass((id)self) == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
+ (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
// 循环遍历父类 直到nil 或者相等
if (tcls == cls) return YES;
}
return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
if (tcls == cls) return YES;
}
return NO;
}
当类方法object_getClass(self) == mate-class