web-dev-qa-db-ja.com

NSDictionaryにキーが存在するかどうかがnullかどうかを確認します

NSDictionaryキーが存在するかどうかを確認する方法を検索し、解決策を考え出しました。しかし、それでも、キーにnull値を追加することを示すエラーがスローされます。私のコードが正しいかどうかはわかりません。誰かこれについて何か考えがあれば私を助けることができます。

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

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

Nullが何も追加していないかどうか、および値を追加していないかどうかを確認します。しかし、それでも理由がわからないエラーが発生します。

/****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'
14
lifemoveson

トミーはこれを完全に説明しました。

私がお勧めするのは、次のようなNSDictionaryクラスの拡張を作成することです。

#import <Foundation/Foundation.h>

@interface NSDictionary (Safety)

- (id)safeObjectForKey:(id)aKey;

@end

そして実装ファイル:

#import "NSDictionary+Safety.h"

@implementation NSDictionary (Safety)

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

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

  return object;
}

@end

そして、コードで[dictionary objectForKey:@"keyName"];を使用する代わりに、

[dictionary safeObjectForKey:@"keyName"];

このように、Tommyが説明したように、nilにメソッド呼び出しを送信すると、アプリはクラッシュしませんが、オブジェクトはnil値を取得します。

お役に立てれば。

14
C0D3

正解は次のとおりです。

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

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

説明ありがとうございました。

14
lifemoveson

以下の答えが私にとってうまくいきました:

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

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

また、次のコマンドを使用して、辞書内のキーの配列を取得できます。

[dictionary allKeys]
7

辞書から返されているオブジェクトがnullかどうかを確認しようとするたびに、これを行います。

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

次に、コードでは次のようになります。

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

それが私があなたのコードで行うことです。

また、念のため、NSDictionaryの結果は定義されていますか?コードでは、設定されているものは何もありません。呼び出された結果を使用する予定の変数として定義されているだけです

6
serenn

キーのオブジェクトが存在しない場合、NSDictionaryはnilを返します。 NSNullは実際のオブジェクトなので、別物です。これは、値があったことを記録できることとその値をnullとして記録できることと、値があったかどうかを記録しないことの違いに似ています。それはまた、単なるオブジェクトではなく、オブジェクトへのポインターの間接参照についてCで考えることにも少し依存しているので、その観点からは完全に意味的には楽しいものではありません。

Objective-Cでは、nilにメッセージを送信でき、結果はnil(または0)であることが保証されます。したがって、C++の場合のように、コードが安全なオブジェクト参照を確保するように設計されている場合、実行していることは不要です。次のような複合ステートメント:

object = [[Type alloc] init];

Allocが失敗してnilを返しても、常に明示的に安全です。発生するのは、initを呼び出しても何も実行されず、nilの送信結果が原因でオブジェクトの値がinitになることです。 to nilnilです。

そうは言っても、ビルとエマニュエルによって提供された答えは正しいはずです。結果を直接nilと比較するか、暗黙的にゼロと比較します。後でクラッシュが発生する場合は、myImageUrlおよびmyImageNSString以外の型であることが期待されているためと考えられます(タイプレスidを元のコードで使用して)、応答しないメッセージを送信しました。

4
Tommy

この別のオプション:

if (![result objectForKey:@"image"])
    {
        NSLog(@"doesn't exist");
    }
    if ([result objectForKey:@"image"])
    {
        NSLog(@"exist");
    }
2
Juan
NSDictionary *result;
NSString *myImageURL = [result objectForKey:@"url"];
if (myImageURL == NULL)
    myImageURL = @"";

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

NULLクラスを考え直すのではなく、それが機能するかどうかを確認します。

2
Bill Burgess

それは私にとってはうまくいかなかった、私はそれをこのように考え出した

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

@Iomecがほとんど持っていた実際の答えはここにあります

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

それが実際の正解です。なぜなら、それはnullであり、myImage = [receivedObject ...];と言うときです。次に、myImage = nilの場合、実行中のバグでない場合、例外であるクラスにnull値(nil)をキャストしていることになります。

1)NSNull null値をテストする2)nilでない場合は割り当てる

コードにまだバグがない場合は、1つのバックグラウンドで8つのアプリを実行しているときに本番環境で動作します。

1
Nick Turner

Nullable辞書objectForKeyinを呼び出すと、アプリがクラッシュするため、クラッシュを回避するためにこの方法でこれを修正しました。

- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;

if (dictionary && (object != [NSNull null])) {
    self.name = [dictionary objectForKey:@"name"];
    self.age = [dictionary objectForKey:@"age"];
}
return self;

}

0
Aleem

JSONKitでも同じ問題が発生しました。そこに実装があります

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

したがって、オブジェクトが存在しない場合、これは間違いなくNULLを返します。次のようにチェックします

NSArray* array = [myDictionary objectForKey:@"a"];
if((NSNull*)arrays!=[NSNull null])
{
  [...]
}
0
Jens Busch
     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
A.G

IS nil。であることを確認するだけでなく、文字列ではないことを確認することで、もう少し安全性を高めたい場合があります。望まないかもしれません。)

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