
目录
一,objc_msgSendSuper
二,方法和内存地址查找
一,objc_msgSendSuper
1,实例代码
// Person
@interface Person : NSObject
@end
@implementation Person
@end
// Student
@interface Student : Person
@end
@implementation Student
- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"%@", [self class]);
NSLog(@"%@", [self superclass]);
NSLog(@"%@", [super class]);
NSLog(@"%@", [super superclass]);
}
return self;
}
@end
// 使用
int main(int argc, char * argv[]) {
@autoreleasepool {
Student *student = [Student new];
}
return 0;
}
// 打印
Student
Person
Student
Person
2,底层代码(用clang
进行转换)
((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"));
((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("superclass"));
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("class"));
((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Student"))}, sel_registerName("superclass"));
// 简化代码
objc_msgSend(self, @selector(class));
objc_msgSend(self, @selector(superclass));
objc_msgSendSuper({self, [Person class]}, @selector(class));
objc_msgSendSuper({self, [Person class]}, @selector(superclass));
3,说明(源码下载地址)
objc_msgSend
// 第一个参数是消息接收者,第二个参数是方法的SEL
OBJC_EXPORT id _Nullable
objc_msgSend(id _Nullable self, SEL _Nonnull op, ...);
objc_msgSendSuper
// 第一个参数是objc_super,第二个参数是方法的SEL
OBJC_EXPORT id _Nullable
objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...);
struct objc_super {
__unsafe_unretained _Nonnull id receiver; // 消息接收者
__unsafe_unretained _Nonnull Class super_class; // 消息接收者的父类
};
class
- (Class)class {
// 返回self所属的类
return object_getClass(self);
}
superclass
- (Class)superclass {
// 返回self所属类的父类
return [self class]->superclass;
}
4,分析
-
用
self
调用方法会转换为objc_msgSend
函数的调用,用super
调用方法会转换为objc_msgSendSuper
函数的调用 -
objc_msgSend
和objc_msgSendSuper
的相同点:消息接收者都是self
class
和superclass
方法内部只用到了消息接收者,所以用self
和用super
调用这两个方法的结果是一样的
-
objc_msgSend
和objc_msgSendSuper
的不同点:objc_msgSend
是从消息接收者所属的类开始查找方法的,而objc_msgSendSuper
是从消息接收者的父类开始查找方法的(这就是super_class
存在的作用)
1>
class
和superclass
方法是由NSObject实现的
2>蓝色是objc_msgSend
查找方法的过程
3>红色是objc_msgSendSuper
查找方法的过程查找方法
二,方法和内存地址查找
1,实例代码
// Person
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)print;
@end
@implementation Person
- (void)print {
NSLog(@"my name is %@", _name);
}
@end
// 使用
- (void)viewDidLoad {
[super viewDidLoad];
NSString *string = @"111";
id cls = [Person class];
void *obj = &cls;
[(__bridge id)obj print];
}
// 打印
my name is 111
2,问题一:obj
不是Person对象,为何调用print
方法能成功?
- 对比代码
// 使用
- (void)viewDidLoad {
[super viewDidLoad];
Person *person = [Person new];
person.name = @"222";
[person print];
}
// 打印
my name is 222
- 图解

- 分析
1>
person
先通过isa
找到Person的class
对象,然后在class
对象中找到
2>同理,obj
通过cls
也可以找到Person的class
对象,所以也能找到
3,问题二:为何_name
的值是111?
- 局部变量
1>局部变量存储在栈区
2>栈区是从高地址往低地址进行分配的
-
string
,cls
,obj
都是局部变量,各占八个字节
1>打印
NSLog(@"%p---%p---%p", &string, &cls, &obj); // 打印 0x7ffeef3ef0d8---0x7ffeef3ef0d0---0x7ffeef3ef0c8
2>图解
局部变量
- 访问
_name
1>Person对象是一个结构体,结构体成员的地址是从低到高依次排列的,所以
_name
的地址高于isa
,另外string
的地址高于cls
2>person
访问_name
时会先跳过isa
,同理,obj
访问_name
时会先跳过cls
,但cls
后面存储的是string
,所以把string
当做_name
来使用了访问_name
4,问题三:为何_name
的值又是ViewController对象?
- 实例代码
// 使用
- (void)viewDidLoad {
[super viewDidLoad];
id cls = [Person class];
void *obj = &cls;
[(__bridge id)obj print];
}
// 打印
my name is <ViewController: 0x7fb6ddd02a90>
- 将
[super viewDidLoad]
转换一下
- (void)viewDidLoad {
struct objcSuper = {self, [UIViewController class]};
objc_msgSendSuper(objcSuper, @selector(viewDidLoad));
id cls = [Person class];
void *obj = &cls;
[(__bridge id)obj print];
}
- 分析
1>
objcSuper
是局部变量,代替了之前string
的位置
2>objcSuper
中self
的地址较低,所以obj
跳过cls
找到的就是self
了self
网友评论