2

来自“objc.h”:

typedef struct objc_class *Class;

但在“runtime.h”中:

struct objc_class {
    Class isa;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

究竟是Class什么?

4

2 回答 2

10
typedef struct objc_class *Class;

^ 这是objc_class指针的前向声明。它给了它一个好听的名字Class

现在让我们看一下objc_class结构:(删除 Objective-C 2.0 检查以缩短它)

struct objc_class {
    Class isa;
};
//This is really saying
struct objc_class {
    struct objc_class *isa;
};

所以现在我们有了一个指向它自己类型的结构。但你为什么要问?

摘自Objective-C 运行时内部,第 2 部分

Class' isa (the Class' Class) 指向的Class 在其objc_method_list 中包含Class' 类方法。了解?运行时使用的术语是,当对象的 isa 指向它的类时,类的 isa 指向对象的“元类”。

那么元类的 isa 指针呢?嗯,它指向层次结构的根类(大多数情况下为 NSObject)。(在 Foundation 框架中,NSObject 子类的每个元类“isa”都是 NSObject 的实例。)是的,顺便说一下,NSObject 的元类的 isa 指向同一个结构——它是一个循环引用,所以没有类的 isa永远为 NULL。


因此,根据该描述,当您创建一个继承自NSObject您的类时isa,它指向其类类型,该类类型指向其元类,该元类指向其根类(NSObject),其中包含对自身的循环引用。这就解释了为什么它需要两个步骤来确定一个对象是一个实例还是一个类

假设您创建了以下类:

@interface MyClass : NSObject
@end
@implementation MyClass
@end


如果您能够* 遍历 isa 指针,您将获得以下信息:
*由于受保护,您不能isa。请参阅下面的 Cocoa with Love 帖子以创建您自己的实现。

Class c = myClassInstance->isa; //This would be the MyClass
c = c->isa; //This would be MyClass' meta class
c = c->isa; //This would be NSObjects meta class
c = c->isa; //This going forward would still be the NSObjects meta class
...

一旦c == c->isa你知道你在根对象。请记住,Objective-C 是 C 的适当超集,它本身不具有面向对象的构造,例如继承。这与其他实现细节一起,例如指向构成完整类层次结构的超类的指针,允许 Objective-C 提供面向对象的特性。有关类和元类的更多信息,请参阅 Cocoa with Love 上的帖子:Objective-C 中的元类是什么?

于 2012-06-29T19:39:58.927 回答
0

关于循环引用:

如果 isa 被定义为不是如下的指针,则它成为循环引用。

struct objc_class {
    struct objc_class isa;
}; 

因为编译器无法计算 objc_class 的大小。

但是,在以下情况下(真实定义),

struct objc_class {
    struct objc_class *isa;
}; 

isa 只是一个指针,所以没有问题。

于 2013-05-18T03:59:47.850 回答