2011-11-08 29 views
6


Tôi muốn có một NSSet đơn giản được nạp với một số NSNumbers và sau đó tìm hiểu xem những con số đó đã được thêm vào trong bộ hay chưa. Khi tôi làm điều này:NSSet của NSNumbers - phương pháp thành viên luôn là nil

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
[set addObject:num1]; 
if([set member:num2]){ 
    // something... 
} 

Vấn đề là thành viên luôn trả về nil (nếu là sai), ngay cả khi các số đó giống nhau. Phương thức isEqual trả về true. Vì vậy,

if([num1 isEqual:num2]){ 
    // correct 
} 

công trình ...
Trong tài liệu tôi đọc rằng phương pháp thành viên sử dụng isEqual vì vậy tôi không biết vấn đề là gì ... Cảm ơn lời khuyên.

+0

nếu mã của bạn được dán chính xác - bạn không thêm đối tượng num2 vào tập hợp – Maggie

+0

của bạn là bạn chắc chắn .. mã của bạn đang hoạt động hoàn toàn tốt cho tôi! – Devarshi

+0

@Maggie vâng tôi chắc chắn, điểm là tôi muốn kiểm tra xem số 5 đã có trong bộ chưa, nhưng tôi phải dùng nsnumber vì chúng là đối tượng, vì vậy tôi muốn kiểm tra xem đối tượng nsnumber có giá trị là 5 không đã có trong tập (num1 với giá trị 5 là, vì vậy nó phải trả về true) – haluzak

Trả lời

2

Vấn đề là, bạn đang kiểm tra xem num1num2 là cùng một đối tượng hay không. Và họ thì không. Chúng chỉ có cùng giá trị nhưng chúng là hai đối tượng khác nhau có cùng giá trị.

Vì vậy, những gì bạn đang kiểm tra với member là liệu chúng có cùng địa chỉ trong bộ nhớ hay không.

Chỉnh sửa: Bạn nên sử dụng compare để kiểm tra xem các giá trị của các số có giống nhau hay không!

+0

"cho dù họ có cùng một địa chỉ trong bộ nhớ "là không đúng sự thật; theo 'thành viên:' docs: "Nếu tập hợp chứa một đối tượng bằng đối tượng (được xác định bởi isEqual :) thì đối tượng đó (thường sẽ là đối tượng), nếu không thì không." – Wevah

+0

Cả hai bạn có thể đúng ...Tôi dường như nhớ lại rằng NSNumber có một tối ưu hóa lén lút, nơi nó có đại diện tĩnh của một số nguyên đầu tiên. Trong trường hợp này, địa chỉ bộ nhớ _and_ isEqual sẽ hoạt động. – jrturton

+0

Chắc chắn, nhưng nó không nên trả về false theo một trong hai cách. – Wevah

4

Cần so sánh các giá trị của NSNumbers, không phải đối tượng.

Bạn có thể sử dụng objectsPassingTest:

Ví dụ:

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
NSNumber *num3 = [NSNumber numberWithInt:3]; 
[set addObject:num1]; 

NSSet *filteredSet; 
filteredSet = [set objectsPassingTest:^(id obj,BOOL *stop){ 
    return [obj isEqualToNumber:num2]; 
}]; 
NSLog(@"Contains num2: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

filteredSet = [set objectsPassingTest:^(id obj,BOOL *stop){ 
    return [obj isEqualToNumber:num3]; 
}]; 
NSLog(@"Contains num3: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

NSLog đầu ra:

Contains num2: YES 
Contains num3: NO 

Hoặc nếu sử dụng các vị từ được mong muốn:

filteredSet = [set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@", num2]]; 
NSLog(@"Contains num2: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 

filteredSet = [set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"SELF == %@", num3]]; 
NSLog(@"Contains num3: %@", (filteredSet.count == 1) ? @"YES" : @"NO"); 
2

Các cá tuyết e làm việc kể từ Xin chào từ được ghi vào nhật ký khi tôi chạy nó

NSMutableSet *set = [[NSMutableSet alloc] init]; 
NSNumber *num1 = [NSNumber numberWithInt:5]; 
NSNumber *num2 = [NSNumber numberWithInt:5]; 
[set addObject:num1]; 
if([set member:num2]){ 
    NSLog(@"Hello, world"); 
    } 
+0

Điều này không hoàn toàn hợp lệ vì nếu tôi thay đổi giá trị của * num1 thành 6 sau khi tôi đã thêm nó vào tập hợp và sau đó hỏi là [set member num1] và [set member num2] cả hai đều trả về true. –

+0

@RyanHeitner, Làm thế nào bạn có thể thay đổi một đối tượng NSNumber? Họ là bất biến! – ragnarius

+0

NSNumber * num1 = [Số NSNumberWithInt: 5]; [set addObject: num1]; num1 = [Số NSNumberWithInt: 6]; –

4

Khi bạn sử dụng NSArray bạn cần phải so sánh các giá trị thay vì các đối tượng bản thân. Thay vì sử dụng NSArray, bạn có thể sử dụng NSMutableIndexSet. Điều này cho phép bạn so sánh các giá trị với một vài bước ít hơn.

//during init, add some numbers 
NSMutableIndexSet *tSet = [[NSMutableIndexSet alloc] init]; 
NSUInteger exampleValue = 7; 
[tSet addIndex:exampleValue]; 
exampleValue = 42; 
[tSet addIndex:exampleValue]; 

//...later on 
//look to see if numbers are there 
if ([tSet containsIndex:7]){ 
    NSLog(@"7 exists!"); 
} 
if ([tSet containsIndex:8]){ 
    NSLog(@"8 exists!"); 
} 

Đầu ra: 7 tồn tại!

Các vấn đề liên quan