2011-08-11 8 views
13

Tôi đã tìm kiếm cách kiểm tra xem khóa NSDictionary có tồn tại hay không và đã đưa ra giải pháp. Nhưng nó vẫn ném cho tôi một lỗi nói rằng thêm giá trị null vào khóa. Tôi không chắc liệu mã của tôi có đúng hay không. Nếu bất cứ ai có bất kỳ ý tưởng về điều này có thể giúp tôi.Kiểm tra xem khóa có tồn tại trong NSDictionary là null hay không

NSDictionary *result; 
id myImageURL = [result objectForKey:@"url"]; 
if ((NSNull *)myImageURL == [NSNull null]) 
    myImageURL = @""; 

id myImage = [result objectForKey:@"image"]; 
if ((NSNull *)myImage == [NSNull null]) 
    myImage = @""; 

Kiểm tra xem null có thêm gì và nếu không thêm giá trị. Nhưng nó vẫn cho tôi một lỗi không biết tại sao.

/****OUTPUT*****/ 

2011-08-11 14:56:06.668 Tab_Table_Win[6510:207] RESULTS : { 
image = "<UIImage: 0xbc332c0>"; 
url = "http://a3.twimg.com/profile_images/999228511/normal.jpg"; 
} 

2011-08-11 14:56:06.669 Tab_Table_Win[6510:207] url : http://a3.twimg.com/profile_images/999228511/normal.jpg 
2011-08-11 14:56:06.670 Tab_Table_Win[6510:207] IMage : <UIImage: 0xbc332c0> 

/*****Breaks Here ***/ 

2011-08-11 14:56:06.876 Tab_Table_Win[6510:207] RESULTS : { 
} 
2011-08-11 14:56:06.878 Tab_Table_Win[6510:207] url : (null) 
2011-08-11 14:56:06.879 Tab_Table_Win[6510:207] IMage : (null) 
2011-08-11 14:56:06.881 Tab_Table_Win[6510:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key' 
+0

Lỗi chính xác mà nó cung cấp là gì và dòng mã nào? – Chuck

+0

Tôi đã chỉnh sửa mã của mình ở trên. – lifemoveson

+0

kiểm tra câu trả lời của tôi.bằng cách gửi nó vào một id sau đó đúc nó, bạn đang lãng phí bộ nhớ, mặc dù rất thấp. Bạn có thể làm điều đó một dòng. Tôi ước iOS có một thuộc tính keysExist như .net. –

Trả lời

2
NSDictionary *result; 
NSString *myImageURL = [result objectForKey:@"url"]; 
if (myImageURL == NULL) 
    myImageURL = @""; 

NSString *myImage = [result objectForKey:@"image"]; 
if (myImageURL == NULL) 
    myImage = @""; 

Xem nếu mà làm việc, chứ không phải là overthinking lớp NULL.

+0

Nopes. Tôi đã NSLog và tôi nhận được câu trả lời này: kết quả: { } và sau đó nó phá vỡ. Không có ý tưởng gì sai? – lifemoveson

+0

Bạn đã thực hiện NSLog trên myImageURL? Trước khi kiểm tra null? Tôi có lẽ sẽ kiểm tra trước và sau. NSLog (@ "result:% @", [result objectForKey: @ "url"]); NSLog (@ "myImageURL:% @", myImageURL); –

6

Bất cứ khi nào tôi cố gắng để kiểm tra xem một đối tượng được trả lại từ một cuốn từ điển được null, tôi làm điều này:

id obj = [myDictionary objectForKey:entityKeyName]; 
if (obj == [NSNull null]) { 
    // do something 
} 

Sau đó, trong mã của bạn, nó sẽ là:

NSDictionary *result; 
NSString *myImageURL = [result objectForKey:@"url"]; 
if (myImageURL == [NSNull null]) 
    myImageURL = @""; 

Đó là những gì tôi sẽ làm trong mã của bạn.

Ngoài ra, chỉ cần đảm bảo là kết quả NSDictionary được xác định? Trong mã của bạn, nó không có bất cứ điều gì nó đang được thiết lập để. Nó chỉ được định nghĩa là biến mà bạn định sử dụng kết quả được gọi là

+0

U cần phải đẳng cấp với NSNull cho bất kỳ NSString nào. – lifemoveson

4

Nếu một đối tượng không tồn tại cho khóa, NSDictionary sẽ trả về nil. An NSNull là một đối tượng thực tế, và do đó một điều khác biệt. Nó giống như sự khác biệt giữa việc có thể ghi lại rằng có một giá trị và giá trị là null và không ghi lại liệu có giá trị hay không. Nó cũng dựa một chút vào bạn suy nghĩ trong các điều khoản C của sự gián tiếp của một con trỏ đến một đối tượng chứ không phải chỉ là một đối tượng, do đó, nó không hoàn toàn hài lòng về mặt ngữ nghĩa từ quan điểm đó.

Trong Mục tiêu-C, bạn có thể gửi bất kỳ thư nào đến nil và kết quả được đảm bảo là nil (hoặc 0). Vì vậy, nếu mã của bạn được thiết kế để đảm bảo rằng bạn có một tham chiếu đối tượng an toàn, như bạn có thể trong C + +, thì những gì bạn đang làm là không cần thiết. Các phát biểu hợp chất như:

object = [[Type alloc] init]; 

Luôn rõ ràng an toàn, ngay cả khi phân bổ không thành công và trả lại nil. Tất cả những gì sẽ xảy ra là cuộc gọi tới init sẽ không làm gì cả và đối tượng sẽ kết thúc với giá trị nil vì kết quả gửi init đến nil cũng là nil.

Điều đó đang được nói, các câu trả lời do Bill và Emmanuel cung cấp phải chính xác. So sánh kết quả của bạn trực tiếp với nil hoặc ngầm đến 0. Nếu bạn đang gặp phải sự cố sau này, tôi đoán đó là vì bạn đang mong đợi myImageUrlmyImage là các loại khác với NSString (Tôi nhận thấy bạn đã sử dụng mã id không cần thiết trong mã ban đầu của bạn) và gửi cho họ một thông báo không trả lời.

13

Câu trả lời đúng là:

NSDictionary *result; 
NSURL *myImageURL = [result objectForKey:@"url"]; 
UIImage *myImage = [result objectForKey:@"image"]; 

/**** Correct way ****/ 
if (myImageURL != nil && myImage != nil) { 
    [images setObject:myImage forKey:myImageURL]; 
} 

Cảm ơn bạn cho tất cả các lời giải thích.

+1

Bạn có thể giải thích nó như thế nào? – lifemoveson

2

này một lựa chọn:

if (![result objectForKey:@"image"]) 
    { 
     NSLog(@"doesn't exist"); 
    } 
    if ([result objectForKey:@"image"]) 
    { 
     NSLog(@"exist"); 
    } 
1

mà không được làm việc cho tôi, tôi figured it out như thế này

id myImageURL = [result objectForKey:@"url"]; 
if ([myImageURL isKindOfClass:[NSNull class]]) 
    myImageURL = @""; 
1

Được rồi đây là câu trả lời thực tế mà @Iomec gần như đã

UIImage *myImage = ([result objectForKey:@"image"] != [NSNull null] ? [result objectForKey:@"image"] : nil); 

Đó là câu trả lời đúng thực tế bởi vì, nó có dạng null và khi bạn nói myImage = [receivedObject ...]; sau đó nếu myImage = nil, bạn đang có hiệu lực đúc một giá trị null (nil) vào một lớp đó là một ngoại lệ, nếu không phải là một lỗi đang chạy.

Bạn nên: 1) thử nghiệm cho NSNull giá trị null 2) nếu không con số không sau đó gán

Nếu bạn mã đã không nghe trộm ra được nêu ra, nó sẽ sản xuất khi bạn có 8 ứng dụng đang chạy ở chế độ nền một ngày.

0

Tôi gặp vấn đề tương tự với JSONKit. Việc triển khai có

- (id)objectForKey:(id)aKey 
{ 
    [...] 
    return((entryForKey != NULL) ? entryForKey->object : NULL); 
} 

Vì vậy, điều này chắc chắn sẽ trả về NULL nếu đối tượng không có ở đó. Tôi kiểm tra xem nó như sau

NSArray* array = [myDictionary objectForKey:@"a"]; 
if((NSNull*)arrays!=[NSNull null]) 
{ 
    [...] 
} 
7

câu trả lời dưới đây làm việc cho tôi:

https://stackoverflow.com/a/2784675/936957

if ([dictionary objectForKey:key]) { 
    // previously stored data for "key" 
} 

Cũng lưu ý rằng bạn có thể nhận mảng của các phím trong một cuốn từ điển sử dụng

[dictionary allKeys] 
+0

Đây là câu trả lời hay nhất, không cần một biến treo xung quanh nếu từ điển thậm chí không có khóa. đặt nó trong câu lệnh if. +1 –

+0

Điều này có vẻ như nó sẽ làm việc, nhưng nó không. objectForKey vẫn trả về true nếu có NSNull null – quantumpotato

+0

@quantumpotato, NSDictionary: objectForKey: trả về nil, nếu khóa không tồn tại trong từ điển, xem [Tham chiếu lớp cho NSDictionary] (https://developer.apple.com/library/ mac/documentation/Cocoa/Reference/Foundation/Lớp/NSDictionary_Class/# // apple_ref/occ/instm/NSDictionary/objectForKey :). Tuy nhiên, tôi đã thử nghiệm nó, có vẻ là làm việc mà không có vấn đề –

11

Tommy giải thích điều này một cách hoàn hảo.

gì tôi khuyên bạn nên là tạo ra một phần mở rộng của lớp NSDictionary như:

#import <Foundation/Foundation.h> 

@interface NSDictionary (Safety) 

- (id)safeObjectForKey:(id)aKey; 

@end 

Và các tập tin thực hiện:

#import "NSDictionary+Safety.h" 

@implementation NSDictionary (Safety) 

- (id)safeObjectForKey:(id)aKey { 
    NSObject *object = self[aKey]; 

    if (object == [NSNull null]) { 
    return nil; 
    } 

    return object; 
} 

@end 

Và thay vì sử dụng [dictionary objectForKey:@"keyName"]; trong mã của bạn, sử dụng

[dictionary safeObjectForKey:@"keyName"]; 

Bằng cách này, như Tommy đã giải thích, bạn sẽ gửi một cuộc gọi phương thức đến một nil wh ich sẽ không sụp đổ các ứng dụng nhưng đối tượng của bạn sẽ nhận được một giá trị nil.

Hy vọng điều này sẽ hữu ích.

0
 1. Results Dictionary after JSON parsing: 

     //if hits success 

     {"result":{"action":"authentication","statusCode":"200","statusMsg":"No 
     error, operation 
     successful.","count":1,"data":{"apiToken":"509e6d21-4f69-4ded-9f3d-4537e59e6a3a","userId":8,"role":"Bidder","firstName":"bidder","lastName":"bidder","emailAddress":"[email protected]","countiesCovered":"21,16,11,1,2,14,32,3,4,25,13,15,5,41,43,6,12,7,24,39,17,36,42,44,29,40,8,18,19,27,9,28,23,10,33,26,35,20,30,22,34,31"}}} 

//Data is Dictionary inside Result 


----------------------------------------------------------------------- 
      I had an error showing : NULL DATACould not cast value of type 'NSNull' (0xda7058) to 'NSDictionary' (0xda6d74) and the result was 
     the following. 

      ({"result":{"action":"authentication","statusCode":"204","statusMsg":"Invalid 
     Username or Password","count":null,"data":null}}) 

      I fixed the Null check of dictionary. 

           if (result.objectForKey("data") is NSNull) 
           { 
      print ("NULL DATA") 

           } 
           else 
           { 
            let data = result["data"]as! NSDictionary 
            print (data) 

           } 
0

Có thể muốn thêm an toàn hơn một chút bằng cách kiểm tra để đảm bảo rằng nó KHÔNG phải là chuỗi thay vì chỉ kiểm tra xem đó có phải là số không. (Để đảm bảo rằng đó không phải là số hoặc bất kỳ thứ gì khác mà bạn có thể không muốn.)

id myImageURL = [result objectForKey:@"url"]; 
if (![myImageURL isKindOfClass:[NSString class]]) { 
    myImageURL = @""; 
}