问题
http://blog.sunnyxx.com/2014/11/06/runtime-nuts/ 问题来源。
(1) 下面的代码输出什么?
@implementation Son : Father |
2016-10-10 19:01:35.752 runtimeDemo[10090:342354] Son
2016-10-10 19:01:36.244 runtimeDemo[10090:342354] Son
当调用[self class]方法时,会转化为objc_msgSend函数,这个函数定义如下:
- id objc_msgSend(id self, SEL op, ...)
self:指向当前调用方法的对象。相当于 [son class];
2.当调用[super class]方法时,会转化为objc_msgSendSuper,这个函数定义如下:
- id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
- struct objc_super {
id receiver;
Class superClass;
};
其实调用super,告诉编译器,调用 class 这个方法时,要去父类的方法,而不是本类里的。
步骤:1.构建objc_super结构体 receiver=son. superClass = Father;
2.objc_msgSendSuper 将(super, op)传递
3.objc_super->receiver 查找superClass(Father)的方法列表,如果没有找到,就去NSObject中查找,找到-class方法后,[objc_super->receiver(son) class];
总结 SEL查找从继承体系中网上查找 但receiver不变。
(2) 下面代码的结果?
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; |
YSE NO NO NO
isMemberOfClass: 判断对象是否为某个特定类的实例。
isKindOfClass: 判断对象是否为某类或派生类的实例。
+ (Class)class {
return
self;
}
- (BOOL)isKindOf:aClass
{
Class cls;
for
(cls = isa; cls; cls = cls->superclass)
if
(cls == (Class)aClass)
return
YES;
return
NO;
}
BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
- (BOOL)isMemberOf:aClass
{
return
isa == (Class)aClass;
}
BOOL res3 = [(id)[Sark class] isKindOfClass:[Sark class]];
根据这个for循环, 我们知道,Sark的isa指针指向NSObject [Sark class] ==Sark.第一次不相等,之后就更不相等了。
(3) 下面的代码会?Compile Error / Runtime Crash / NSLog…?
@interface NSObject (Sark) |
[NSObject foo];结果会调用-(void)foo
因为NSObject的元类的superClass ->NSObject 类 -方法和+方法,只是查找的体系不一样,但是实现原理是通过对象,找到对应的SEL即方法名去查找。
(4) 下面的代码会?Compile Error / Runtime Crash / NSLog…?
@interface Sark : NSObject |
2016-10-11 19:53:00.542 runtimeDemo[16341:945488] my name's <ViewController: 0x7fc8b3f03b70>
Propertyname最终被转换成了Ivar加入到了类的结构中,Runtime通过计算成员变量的地址偏移来寻找最终Ivar的地址。这里的原因主要是因为在C中,局部变量是存储到内存的栈区,程序运行时栈的生长规律是从地址高到地址低。C语言到头来讲是一个顺序运行的语言,随着程序运行,栈中的地址依次往下走。