在Objective-C中的字符串比较与类比较

时间:2011-11-24 00:10:55

标签: iphone objective-c cocos2d-iphone objective-c++ game-loop

我正在编写一个Objective-C游戏,我正处于我应该开始在游戏循环中优化我的一些代码的阶段。
我使用了大量的类比较方法,

  

if([obj isMemberOfClass:[SomeClass class]])

等。
我听说这种检查非常昂贵,因为我选择只有1个数组填充多个类,我需要进行某种类检查。
我想也许在NSObject子类化NSObject中添加一个属性来包含一个字符串属性,在初始化过程中我将使该等特定子类的类名等于。然后干脆做一个

  

if([obj.klass isEqualTo:@“SomeClass”])

这会有益吗?
我试图尽可能多地保持游戏循环中的动态编码。

谢谢!

2 个答案:

答案 0 :(得分:10)

简答:不。与比较(或:分类,分类)对象的其他方法相比,字符串比较过于昂贵。

答案很长:不要优化你没有分析,测量和比较的东西。在开始优化之前,您真正想要做的是清楚地了解应用程序的行为方式以及性能瓶颈。您尝试的更改不太可能导致性能发生任何明显变化,因此我建议首先找到真正的瓶颈。

在这种特殊情况下,如果测试失败,发送isEqual到NSString比isMemberOfClass慢4倍。这样的条件测试大部分时间都会失败,这就是为什么你应该忽略测试成功的结果。

成功的字符串比较很快,因为它是一个简单的指针比较,如果两个字符串相等,它们很可能指向相同的内存地址。如果它们不相等,则可能会使用哈希方法比较字符串中的每个字符是否相等。

以下是我添加到performance test project的对象比较测试的结果。您可以使用该项目进行进一步的测试。

enter image description here

答案 1 :(得分:2)

这不是你问题的直接答案,而是广义上的答案。

在Objective-C中,哲学更像是Smalltalk,你在其中发送消息并让对象决定如何处理它。如果您发现自己不得不进行大量测试以查看对象是什么类,则需要重新考虑您的设计。

例如,如果你有一个对象数组,并且你想将每个对象转换为一个整数来对它做一些数学运算,你可以这样做:

for (id anObj in array)
{
    int anInt = [anObj intValue];
    // do something with anInt
}

每个anObj的类别无关紧要,您可以向其发送-intValue。例如,如果您的数组中包含NSStringsNSNumbers,则无关紧要,上面的代码将按预期执行。

许多类没有为选择器-intValue定义方法。例如,如果您将该消息发送到NSData的实例,它将通过抛出异常来响应。根据具体情况,有几种方法可以解决这个问题。

  1. 通过测试查看对象是否知道选择器来忽略不响应选择器的对象

    for (id anObj in array)
    {
        if ([anObject respondsToSelector: @selector(intValue)])
        {
            int anInt = [anObj intValue];
            // do something with anInt
        }
    }  
    
  2. 为您知道将放入数组的所有类定义选择器。这是通过声明category来完成的。这样,您可以扩展任何Objective-C类而无需子类化。例如,您可以为NSData定义一个intValue方法,该方法返回其长度,或其字节总和或其他一些适当的值。

  3. 通过声明protocol来正式化要求。然后,您可以测试协议的一致性,或者依靠编译时检查来确保放入阵列的对象符合协议。

  4. 您可以做很多事情,但是您需要从类层次结构的C ++ / Java模型中略微偏离。 Objective-C在这方面更加灵活。