【问题标题】:Check if NSString instance is contained in an NSArray检查 NSString 实例是否包含在 NSArray 中
【发布时间】:2011-08-14 05:52:05
【问题描述】:

我有一个包含一堆字符串的数组,我想检查某个字符串是否包含在数组中。如果我在数组上使用 containsObject: 消息,我会得到正确的结果。是否所有具有相同字符串的NSString 对象都指向同一个对象?或者为什么containsObject: 工作?

NSArray *stringArray = [NSArray arrayWithObjects:@"1",@"2",@"3",anotherStringValue, nil];
if([stringArray containsObject:@"2"]){
  //DO SOMETHING
}

【问题讨论】:

    标签: cocoa nsstring nsarray


    【解决方案1】:

    是的,硬编码的 NSStrings(字符串文字)(即源代码中的任何 @"...")会在您的进程运行时转换为无限期存在的字符串。

    然而 NSArraycontainsObject: 方法在其对象上调用 isEqual:,因此 即使是动态创建的字符串,例如 [NSString stringWithFormat:@"%d", 2] 也会返回 @ 987654326@ 在您的示例 sn-p 中。
    这是因为 NSString 的 isEqual:(或更准确地说是它的 isEqualToString:)方法被实现为内容感知(相对于比较指针标识),因此对于包含完全相同的字符序列(在比较时),无论它们是如何以及何时创建的。

    要检查是否相等(指针)身份,您必须枚举您的数组并通过比较

    NSString *yourString = @"foo";
    BOOL identicalStringFound = NO;
    for (NSString *someString in stringArray) {
        if (someString == yourString) {
            identicalStringFound = YES;
            break;
        }
    }
    

    (不过,您很可能不想要)。

    或者以更方便的方式:

    BOOL identicalStringFound = [stringArray indexOfObjectIdenticalTo:someString] != NSNotFound;
    

    (你很可能也不想要这个)。


    总结:

    所以你得到containsObject: 的肯定回复的原因是NOT 因为文字字符串共享相同的常量实例,BUT 因为containsObject: 按照惯例调用isEqual:,内容感知。

    您可能希望阅读来自NSObject protocolisEqual: 的(简短)文档。

    【讨论】:

      【解决方案2】:

      containsObject: 执行值检查,而不是指针检查。它使用 NSObject 定义的 isEqual: 方法,并被其他对象覆盖以进行测试。因此,如果两个字符串包含相同的字符序列,它们将被认为是相同的。

      在某些情况下,指针测试和值测试之间的区别非常重要。源代码中定义的常量字符串由编译器组合成同一个对象。但是,动态创建的字符串不是同一个对象。这是一个示例程序,将演示这一点:

      int main(int argc, char **argv) {
          NSAutoreleasePool *p = [NSAutoreleasePool new];
          NSString *constantString = @"1";
          NSString *constantString2 = @"1";
          NSString *dynamicString = [NSString stringWithFormat:@"%i",1];
          NSArray *theArray = [NSArray arrayWithObject:constantString];
          if(constantString == constantString2) NSLog(@"constantString == constantString2");
              else NSLog(@"constantString != constantString2");
          if(constantString == dynamicString) NSLog(@"constantString == dynamicString");
              else NSLog(@"constantString != dynamicString");
          if([constantString isEqual:dynamicString]) NSLog(@"[constantString isEqual:dynamicString] == YES");
              else NSLog(@"[constantString isEqual:dynamicString] == NO");
          NSLog(@"theArray contains:\n\tconstantString: %i\n\tconstantString2: %i\n\tdynamicString: %i",
                [theArray containsObject:constantString],
                [theArray containsObject:constantString2],
                [theArray containsObject:dynamicString]);
      }
      

      这个程序的输出是:

      2011-04-27 17:10:54.686 a.out[41699:903] 常量字符串 == 常量字符串2
      2011-04-27 17:10:54.705 a.out[41699:903] 常量字符串!=动态字符串
      2011-04-27 17:10:54.706 a.out[41699:903] [constantString isEqual:dynamicString] == 是
      2011-04-27 17:10:54.706 a.out[41699:903] 数组包含:
      常量字符串:1
      常量字符串2:1
      动态字符串:1

      【讨论】:

        【解决方案3】:

        您可以使用containsObject 来查找某个字符串是否存在,

        NSArray *stringArray = [NSArray arrayWithObjects:@"1",@"2",@"3",anotherStringValue, nil];
        
        if ( [stringArray containsObject: stringToFind] ) {
            // if found
        } else {
            // if not found
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-09
          • 2018-11-02
          • 1970-01-01
          • 1970-01-01
          • 2011-10-02
          • 1970-01-01
          • 1970-01-01
          • 2011-11-15
          相关资源
          最近更新 更多