object_getClass(obj)和[obj class]给出不同的结果

时间:2013-04-09 15:30:09

标签: objective-c cocoa-touch objective-c-runtime

调用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) 

2 个答案:

答案 0 :(得分:11)

我怀疑obj,尽管名字,但是是一个班级。例如:

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

原因是Class对象的类是同一个类,但Class的object_getClass是元类(类的类)。这是有道理的,因为Class是元类的一个实例,并且根据文档object_getClass返回“哪个对象是实例的类对象”。 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

答案 1 :(得分:3)

之前的答案是正确的,但不是提问者的答案。

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

当您向实例添加“KVO”时,该实例是isa-swizzled。见Key-Value Observing Implementation Details

其他一些库如ReactiveCocoa也会更改实例的'isa'指针。 (在Source of ReactiveCocoa中搜索'RACSwizzleClass')