6

调用 object_getClass(obj) 和 [obj class] 时,我得到两个不同的对象实例。知道为什么吗?

Class cls = object_getClass(obj);
Class cls2 = [obj class];

(lldb) po cls
$0 = 0x0003ca00 Test
(lldb) po cls2
$1 = 0x0003ca14 Test
(lldb) 
4

2 回答 2

12

我怀疑 obj 尽管有名字,但它是一个类。例子:

Class obj = [NSObject class];
Class cls = object_getClass(obj);
Class cls2 = [obj class];
NSLog(@"%p",cls);  // 0x7fff75f56840
NSLog(@"%p",cls2); // 0x7fff75f56868

原因是Class对象的类是同一个类,而object_getClass一个Class的类是元类(类的类)。这是有道理的,因为 Class 是元类的实例,并且根据文档object_getClass返回“<em>对象是实例的类对象”。LLDB 中的输出将是:

(lldb) p cls
(Class) $0 = NSObject
(lldb) p cls2
(Class) $1 = NSObject
(lldb) po cls
$2 = 0x01273bd4 NSObject
(lldb) po cls2
$3 = 0x01273bc0 NSObject

如果替换Class obj = [NSObject class];NSObject *obj = [NSObject new];,打印 cls 和 cls2 时的结果将相同。那是,

    NSObject *obj = [NSObject new];
    Class cls = object_getClass(obj);
    Class cls2 = [obj class];
    NSLog(@"%p",cls);  // 0x7fff75f56840
    NSLog(@"%p",cls2); // 0x7fff75f56840
于 2013-04-09T16:11:32.933 回答
3

上一个答案是正确的,但不是针对提问者的答案。

对于一个实例(不是一个类),“object_getClass(obj)”和“[obj class]”变得不同的唯一原因是“isa-swizzling”或其他一些改变实例的“isa”指针的swizzling。

当您将“KVO”添加到实例时,该实例是 isa-swizzled。参见Key-Value Observing 实现细节

ReactiveCocoa 等其他一些库也会更改实例的“isa”指针。(在ReactiveCocoa 的来源中搜索“RACSwizzleClass” )

另见此博客(中文):Class-swizzling、Isa-swizzling 和 KVO

于 2016-01-27T12:32:15.963 回答