【问题标题】:Why is [@"" class] != NSClassFromString(NSStringFromClass([@"" class])) on OS X?为什么 [@"" class] != NSClassFromString(NSStringFromClass([@"" class])) 在 OS X 上?
【发布时间】:2013-05-01 17:12:08
【问题描述】:
if([@"" class] == NSClassFromString(NSStringFromClass([@"" class])))
    printf("foo");
else
    printf("bar");

iOS 上的输出:foo

OS X 上的输出:条形

为什么这在 OS X 上表现得那么奇怪?

【问题讨论】:

  • 您是否尝试过使用调试器或日志记录来确定NSStringFromClassNSClassFromString 的结果是什么?
  • 我猜[@"" class] 可以(概念上)有几个不同的值,这取决于 NSString 是否被构造、静态定义等。Cocoa 喜欢为同一个外部类创建多个内部类,并且这些在 iOS 和 OSx 之间可能有所不同。
  • 我在 OS X 和 iOS 上都有 'foo'。两个字符串都是__NSCFConstantString 的同一个私有类。并使用NSLog(); 而不是printf();
  • @Kri: 是的,我已经通过调试器逐步查看了覆盖,将它们存储在变量中时,有趣的是:[@"" class] 和 NSClassFromString(NSStringFromClass([@ "" class])) 在两个操作系统上都显示为 __NSCFConstantString,因此它们在 OS X 上看起来也具有相同的值。
  • @Tom:嗯,我什至将代码复制到了一个全新的空测试项目中,这是我刚刚从 OS X Foundation 命令行工具模板创建的,但我仍然得到 bar。我已经尝试过调试和发布配置、32 位和 64 位以及不同的基础 SDK 和目标平台,但它总是适用于 OS X。你能告诉我你有 foo 的设置吗?

标签: objective-c cocoa operating-system


【解决方案1】:

有趣的问题。下面指出了cmets中提到的一些东西:

Class c1 = [@"" class];
Class c2 = NSClassFromString(NSStringFromClass([@"" class]));

// The names are the same under iOS and OS X
NSLog(@"c1: '%@', c2: '%@'", c1, c2);
// The pointers are the same under iOS but different under OS X
NSLog(@"*c1: '%p', *c2: '%p'", c1, c2);

if (c1 == c2) {
    NSLog(@"== equal"); // iOS
} else {
    NSLog(@"== not equal"); // OS X
}

if ([c1 isEqual:c2]) {
    NSLog(@"isEqual: equal"); // iOS
} else {
    NSLog(@"isEqual: not equal"); // OS X
}

const char *n1 = class_getName(c1);
const char *n2 = class_getName(c2);
if (strcmp(n1, n2) == 0) {
    NSLog(@"name equal"); // Both iOS and OS X
} else {
    NSLog(@"name not equal");
}

在 Mac (OS X 10.7.5) 上,这给出:

2013-05-07 12:35:45.249 测试[27483:303] c1: '_NSCFConstantString', c2: '_NSCFConstantString'
2013-05-07 12:40:06.673 测试[27542:303] *c1: '0x7fff7d2bd740', *c2: '0x7fff7d28ae48'
2013-05-07 12:35:45.250 测试[27483:303] == 不等于
2013-05-07 12:35:45.251 测试[27483:303] isEqual: 不等于
2013-05-07 12:35:45.251 测试[27483:303] 名称相等

在 iOS (6.1) 上,这给出:

2013-05-07 12:38:11.816 测试[27516:11303] c1: '_NSCFConstantString', c2: '_NSCFConstantString'
2013-05-07 12:41:01.319 测试[27557:11303] *c1: '0x1db88f8', *c2: '0x1db88f8'
2013-05-07 12:38:11.816 测试[27516:11303] == 相等
2013-05-07 12:38:11.816 测试[27516:11303] isEqual: equal
2013-05-07 12:38:11.816 测试[27516:11303] 名称相等

关键区别似乎在于,在 iOS 下,两个 Class 值是同一个对象,但在 OS X 下,它们是两个不同的对象。

因此,使用==isEqual: 比较两个Class 值似乎是不安全的,至少在OS X 下是这样。我找不到任何函数来比较两个Class 值所以使用@987654327 @ 似乎是最好的选择。

【讨论】:

  • 我在 OS X 上得到了相同的类(相同的指针)(正如 Tomasz Szulc 在他对该问题的评论中所报告的那样)。
  • 我应该指出我在 OS X 10.7.5 (Lion) 下运行了我的测试。看来 10.8.x 中的结果与 10.7.x 不同。
  • 使用 isKindOf: 与 NSString 进行比较。记住 NSString 是一个类簇。
  • @RobNapier 但这是最​​简单的方法,并且会否定 OP 问题的全部意义。 :)
  • 然而,问题的重点很简单:类是对象,可能有多个实例。甚至可以让类伪装成其他类(KVO 类一直都在这样做),这样它们完全不同但看起来相同。您不能使用== 将对象与它们本身以外的任何东西进行比较。也就是说,我对isEqual: 失败感到有点惊讶,但是类是对象,但在 ObjC 中不是完全对象。 :D 它们有点像对象。
猜你喜欢
  • 2018-01-04
  • 1970-01-01
  • 2012-08-03
  • 1970-01-01
  • 2016-10-05
  • 2015-08-22
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
相关资源
最近更新 更多