OC之runtime面试题(一)

对于LBPerson类,代码如下

@interface LBPerson : NSObject
@property (nonatomic, copy) NSString *name;

- (void)test;
@end
@implementation LBPerson
- (void)test {
    NSLog(@"name = %@", self.name);
}
@end

外面存在以下调用代码,问能否调用成功,如果能打印结果是什么

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *test = @"hhhhh";
    id cls = [LBPerson class];
    void *obj = &cls;
    [(__bridge id)obj test];
    
}

运行之后打印结果如下:

name = hhhhh

从打印结果看,调用成功了,但是打印了viewDidLoad中test的变量的值

首先我们分析为什么能调用成功,对于一般的LBPerson中test的调用:

LBPerson *person = [[LBPerson alloc] init];
[person test];

对于正常的person对象调用test的方式,是通过person对象的isa指针,找到LBPerson类进行调用的

对于[(__bridge id)obj test]的调用,对于上述代码的声明obj->cls->[LBPerson class],在[obj test]调用过程中,会根据obj的指向,取出obj指向地址中前八个字节,而obj指向cls刚好,cls八个字节全部指向[LBPerson class],这也就是能调用成功的原因

下面分析打印结果,打印结果为name = hhhhh

上述代码中内存分配如下图所示:

最终调用test 传入的是cls的地址,而正常的person对象调用时候,取name的值的时候,是根据person对象的地址加八个字节。obj调用的时候相当于在cls地址的基础上加八个字节,刚好是test变量的地址,所以打印的是test变量的值

原文地址:https://www.cnblogs.com/muzichenyu/p/14210494.html