2011-04-27 7 views
71

Tôi có một mảng với một chuỗi các chuỗi và tôi muốn kiểm tra xem một chuỗi nhất định có được chứa trong mảng hay không. Nếu tôi sử dụng thông báo containsObject: trên mảng, tôi sẽ nhận được kết quả chính xác. Làm tất cả NSString đối tượng có cùng một điểm chuỗi cho cùng một đối tượng không? Hoặc tại sao là containsObject: hoạt động?Kiểm tra xem thể hiện NSString có được chứa trong một NSArray

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

Trả lời

156

Vâng, NSStrings mã hóa cứng (xâu) (có nghĩa là bất kỳ @"..." trong mã nguồn của bạn) đều được biến thành chuỗi đang tồn tại vô thời hạn trong khi quá trình bạn đang chạy.

Tuy nhiên NSArray 's containsObject: phương pháp gọi isEqual: trên các đối tượng của nó, do đó thậm chí là một chuỗi động tạo như [NSString stringWithFormat:@"%d", 2]sẽ trở YES trong đoạn mẫu của bạn.
Điều này là do NSString của isEqual: (hay chính xác hơn isEqualToString: của nó) phương pháp được thực hiện để được nội dung nhận thức (so với so sánh bản sắc con trỏ) và do đó trả về YES cho bất kỳ cặp chuỗi có chứa chuỗi rất giống nhau của các nhân vật (tại thời điểm so sánh), bất kể chúng được tạo ra như thế nào và khi nào.

Để kiểm tra các bằng (pointer-) danh tính bạn phải liệt kê mảng của bạn và so sánh qua

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

(mà nhiều khả năng bạn sẽ không muốn, mặc dù).

Hoặc một cách thuận tiện hơn:

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

(nhiều khả năng bạn sẽ không muốn điều này một trong hai).


Tổng hợp:

Vì vậy, lý do bạn nhận được một câu trả lời tích cực từ containsObject:KHÔNG vì chuỗi chữ chia sẻ các trường hợp liên tục cùng, NHƯNGcontainsObject: theo quy ước gọi isEqual: , đó là nội dung nhận thức được.

Bạn có thể muốn đọc tài liệu (ngắn) cho isEqual: từ NSObject protocol.

16

containsObject: thực hiện kiểm tra giá trị, chứ không phải kiểm tra con trỏ. Nó sử dụng phương thức isEqual: được xác định bởi NSObject và được ghi đè bởi các đối tượng khác để thử nghiệm. Do đó, nếu hai chuỗi chứa cùng một chuỗi ký tự, chúng sẽ được coi là giống nhau.

Sự khác biệt giữa kiểm tra con trỏ và kiểm tra giá trị là rất quan trọng trong một số trường hợp. Các chuỗi không đổi được định nghĩa trong mã nguồn được kết hợp bởi trình biên dịch sao cho chúng là cùng một đối tượng. Tuy nhiên, các chuỗi được tạo động không phải là cùng một đối tượng.Dưới đây là một chương trình ví dụ mà sẽ chứng minh điều này:

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]); 
} 

Kết quả của chương trình này là:

2011-04-27 17: 10: 54,686 a.out [41.699: 903] constantString = = constantString2
2011-04-27 17: 10: 54.705 a.out [41699: 903] constantString! = dynamicString
2011-04-27 17: 10: 54.706 a.out [41699: 903] [constantString isEqual: dynamicString] == CÓ
2011-04-27 17: 10: 54.706 a.out [41699: 903] theArray chứa:
constantString: 1
constantString2: 1
dynamicString: 1