2

通常、解析された JSON オブジェクトから大きな NSDirectory がある場合、次のようなコードでこのオブジェクトにアクセスできます。

[[[[[obj objectForKey:@"root"] objectForKey:@"key1"] objectAtIndex:idx] objectForKey:@"key2"] objectAtIndex:idz];

ラインはこれよりもずっと長くなる可能性があります。

このコードを何らかの方法で最適化できますか? せめて読みやすいように?

オブジェクトが対応していない場合、この行も実行時エラーを生成します。これを回避する最も効率的な方法は何ですか?

4

4 に答える 4

4

のように、-objectForKey:使用できるすべてに を使用していた場合-valueForKeyPath:

[obj valueForKeyPath:@"key1.key2.key3.key4"]

ただし、これは を使用する必要がある場合には機能しません-objectAtIndex:。あなたにとって良い解決策はないと思います。-valueForKeyPath:また、実行時エラーの問題も解決しません。

これを行う簡単な方法が本当に必要な場合は、キーの代わりに-valueForKeyPath:を指定するための構文を提供-objectAtIndex:し、適切な動的チェックを行って、オブジェクトが実際に問題の方法。

于 2012-07-04T08:21:35.323 に答える
0

オブジェクトへの完全な「パス」を含む配列を作成できると思います。唯一のことは、おそらく NSNumber に何らかの方法でインデックスを保存する必要があることです。この場合、NSNumber オブジェクトを辞書のキーとして使用することはできません。次に、この特定の「パス」に必要なオブジェクトを返すメソッドを作成します。みたいな

NSMutableArray* basePath = [NSMutableArray arrayWithObjects: @"first", [NSNumber numberWithInt:index], nil];
id object = [self objectForPath:basePath inContainer:container];

- (id) objectForPath:(NSMutableArray*)basePath inContainer:(id)container
{
    id result = nil;
    id pathComponent = [basePath objectAtIndex: 0];
    [basePath removeObjectAtIndex: 0];

    // check if it is a number with int index
    if( [pathComponent isKindOfClass:[NSNumber class]] ) 
    {
        result = [container objectAtIndex: [pathComponent intValue]];
    }
    else
    {
        result = [container objectForKey: pathComponent];
    }

    assert( result != nil );

    // check if it is need to continue searching object
    if( [basePath count] > 0 )
    {
        return [self objectForPath:basePath inContainer: result];
    }
    else
    {
        return result;
    }
}

これは単なるアイデアですが、私の言いたいことを理解していただければ幸いです。そして、Kevin が上で述べたように、インデックスがない場合は、キーと値のコーディングを使用できます。

于 2012-07-04T08:29:10.080 に答える
0

それがあなたに合うかどうかはわかりませんが、ブロックを試すこともできます。私はいつも非常に便利だと思っています. 少なくとも、コードがはるかに読みやすくなりました。

NSArray *filter = [NSArray arrayWithObjects:@"pathToFind", @"pathToFind2",nil];

NSPredicate *filterBlock = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind){        
    NSArray *root = (NSArray*)obj;

    // cycle the array and found what you need.
    // eventually implementing some sort of exit strategy

}];

[rootObject filteredArrayUsingPredicate:filterBlock];
于 2012-07-04T08:36:33.263 に答える
0

コードを読みやすくしたい場合は、このように行をいくつかの行に分割できます

 MyClass *rootObject = [obj objectForKey:@"root"];
 MyClass *key1Object = [rootObject objectForKey:@"key1"];
 MyClass *myObject = [key1Object objectAtIndex:idx];
 ...

など。

于 2012-07-04T08:13:34.030 に答える