返回

揭开isa底层原理:如何理解Person的isa为何指向NSObject?

IOS

探索Person的isa指向

在前一篇文章中,我们对isa有了一些认识。在这篇文章中,我们将继续探索isa的奥秘,重点分析Person的isa为何指向NSObject。

首先,我们定义一个Person类,并在NSLog处打个断点进行调试(以下调试如不做说明,都处于macOS环境下)。

#import <Foundation/Foundation.h>

@interface Person : NSObject

@end

@implementation Person

- (void)sayHello {
    NSLog(@"Hello, world!");
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc] init];
        NSLog(@"Person's isa: %p", person->isa);
    }
    return 0;
}

运行程序,并在NSLog处打上断点。在调试器中,我们可以看到Person的isa指向了NSObject。

(lldb) po person->isa
0x101b506e0

那么,为什么Person的isa会指向NSObject呢?

理解类方法和实例方法

要理解这个问题,我们需要先了解类方法和实例方法的概念。

  • 类方法:类方法是属于类的函数,它可以用类名直接调用,不需要创建类的实例。
  • 实例方法:实例方法是属于类的实例的函数,它必须通过类的实例来调用。

我们可以通过以下代码来演示类方法和实例方法的区别:

#import <Foundation/Foundation.h>

@interface Person : NSObject

+ (void)sayHello;

- (void)sayHello;

@end

@implementation Person

+ (void)sayHello {
    NSLog(@"Hello, world!");
}

- (void)sayHello {
    NSLog(@"Hello, world!");
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 调用类方法
        [Person sayHello];

        // 创建类的实例
        Person *person = [[Person alloc] init];

        // 调用实例方法
        [person sayHello];
    }
    return 0;
}

运行程序,我们可以看到类方法和实例方法都被正确地调用了。

Hello, world!
Hello, world!

揭开谜底

现在,我们回到Person的isa指向NSObject的问题上。

Person的isa指向NSObject,是因为NSObject是Person的父类。在Objective-C中,每个类都有一个父类,父类可以是NSObject,也可以是其他类。

Person的父类是NSObject,因此Person的isa指向NSObject。

总结

在这篇文章中,我们探索了Person的isa指向NSObject的原因,并理解了类方法和实例方法的概念。通过这些知识,我们可以更深入地理解Objective-C的底层原理。