美文网首页
03.runtime答疑

03.runtime答疑

作者: 白开了杯水 | 来源:发表于2021-09-13 17:56 被阅读0次

之前章节
01Class的结构
02.消息机制

1.以下代码输出了什么?
@interface Person : NSObject
@end

@interface Student : Person
@end

@implementation Student
- (instancetype)init
{
    self = [super init];
    if (self) {
        NSLog(@"[self class] = %@", [self class]);
        NSLog(@"[self superclass] = %@", [self superclass]);
        NSLog(@"[super class] = %@", [super class]);
        NSLog(@"[self superclass] = %@", [super superclass]);
    }
    return self;
}
@end

首先self不用说,1和2输出分别是Student和Person,至于3和4,主要考的其实是super的底层,super的底层源码我们使用clang编译为c++代码后如下:

/// Specifies the superclass of an instance. 
struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained _Nonnull id receiver;
    __unsafe_unretained _Nonnull Class super_class;
    /* super_class is the first class to search */
};
  • receiver:消息接收者
  • super_class:看注释很明白,就是找方法从父类方法开始找

那么我们的代码[super class]其实转过来就是大概如下

objc_msgSendSuper({self, Person}, @selector(class));

由于receiver是消息接收者,self对应着receiver,所以最终还是会对self发送class的消息,这时其实相当于[self class]和[self superclass],结果就是Student和Person,如下图

输出结果
2.以下代码输出了什么?
BOOL res1 = [[Student new] isKindOfClass:[Person class]];
BOOL res2 = [[Student new] isMemberOfClass:[Person class]];
BOOL res3 = [[Person class] isMemberOfClass:[NSObject class]];
BOOL res4 = [[Person new] isMemberOfClass:[Person class]];
NSLog(@"%d %d %d %d ", res1, res2, res3, res4);

其实这个主要考察的是isKindOfClass和isMemberOfClass的区别了,这俩个方法分别是在NSObject实现的,而且是开源的,我们可以先看看它们的源码实现

+ (Class)superclass {
    return self->getSuperclass();
}

- (Class)superclass {
    return [self class]->getSuperclass();
}

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = self->ISA(); 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;
}
  • isKindOfClass:比较多次,它首先和cls参数相比,然后继续跟父类相比,也就是会循环到父类去,跟继承有关系
  • isMemberOfClass:比较一次,只跟传进来的cls对比
    输出结果自然是:1 0 0 1
3.以下代码是否能运行成功,可以的话输出什么
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)print;
@end
@implementation Person
- (void)print
{
    NSLog(@"name = %@", self.name);
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    id cls = [Person class];
    void *obj = &cls;
    [(__bridge id)obj print];
}
@end

这道题太蛋疼了,我也不太懂,要画图才能理清思绪

id cls = [Person class];

那么画出来的图如下:

cls内存分布结构模拟图

接下来

void *obj = &cls;
obj内存分布结构模拟图

从图中可以看出,obj指向的是cls的地址,而cls的地址指向的是PersonClass的地址,而PersonClass的地址就是isa的地址(首地址)
最后print方法如下图:

print方法调用内存分布结构模拟图

简单来说,代码里有调用[super viewDidLoad],这里系统会创建一个变量self传入进去给到receiver,所以会分配一个栈空间内存,栈空间内存机制是从高位向地位开始分配器,所以self内存地址会大一些,如0x009这样,然后接下来到cls,这时会分配0x001这样子,当我调用name的属性的时候,isa是0x001,那么加多8个字节,就是0x009,也就是说name的地址值就是0x009,那0x009不就是self吗,所以结果会输入控制器值:name = ViewController: 0x....这样

相关文章

  • 03.runtime答疑

    之前章节01Class的结构[https://www.jianshu.com/p/c3049e046f73]02....

  • 0919晨读感悟-教学里的效率观

    答疑 才来学校的时候,不能给学生上课,主任就安排我答疑。我想,哦,答疑就答疑。学生上晚自习时,我夹着一本书就进了教...

  • 答疑类产品——作业帮、小猿搜题、学霸君竞品分析

    一、分析目的 针对K12领域的答疑类产品,进行调研: (一)答疑类产品的市场现状 (二)分析答疑类产品的产品模式 ...

  • 听答疑发现了学长的优点

    本来应该听今天的答疑,但我目前的状态,更适合之前的答疑。 随便打开的,听见白虹姐的答疑。听着听着,突然发现:...

  • 2016年12月11日的群资料整理

    2016年12月11日的群资料整理目录 课后答疑一:不好的标签是什么? 课后答疑二:情绪的来源 课后答疑三:活在当...

  • 【答疑】151217答疑笔记

    ★问自己: 我要什么? 我怎么一步一步得到? 第一步怎么做? ★区分目标与手段:手段就是“我通过……手段,可以达成...

  • 答疑

    一直苦苦寻找 什么是幸福什么是成功什么是情感 今天晚饭前跟妈妈通了电话晚饭后老婆孩子侄子陪着我散步 我知道了前面三...

  • 答疑

    彻骨寒,物是人非终不变,奈何残月未圆,由它去吧! 心已冷,故人驾鹤岂能安,难抵世俗凡事,一切随缘! 宵夜明,血肉亲...

  • 答疑

    Q:好想重新調整下我的節奏。我的大方向開始亂了。好多以前的自己消失了。漸漸跟生活磨合不了,清楚明白,這並不是我要的...

  • 答疑

    昨天晚上10:00 丫丫主会场第一次面向社会公开答疑解惑,只有能在思涵创业平台享受思涵老师的: 行善积德...

网友评论

      本文标题:03.runtime答疑

      本文链接:https://www.haomeiwen.com/subject/avffgltx.html