2012-07-04 2 views
2

Si j'ai un grand NSDirectory généralement d'un JSON objet analysable je peux accéder à cet objet avec le code comme ceci:Comment accéder efficacement aux objets volumineux dans Obj-C en utilisant objectForKey et objectAtIndex?

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

La ligne pourrait être beaucoup plus que cela. Puis-je optimiser ce code de quelque façon que ce soit? Au moins, le rendre plus facile à lire?

Cette ligne générera également une erreur d'exécution si l'objet ne correspond pas, quel est le moyen le plus efficace d'éviter cela?

+0

Si vous utilisez la bonne version de Xcode vous pouvez faire ceci: 'obj [@ "root"] [@ "key1"] [IDX] [@ "key2"] [idz]' - légèrement plus lisible (et rétrocompatible) mais pas vraiment le chemin à parcourir ... – hypercrypt

+0

C'est très sympa! Semble ne pas fonctionner dans 4.3.2 !? – Gustav

+0

Xcode 4.4 est votre ami. Developer Preview est disponible maintenant, la finale sera disponible ce mois-ci. – hypercrypt

Répondre

4

Si vous utilisez -objectForKey: pour tout ce que vous pouvez utiliser -valueForKeyPath:, comme dans

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

Cependant, cela ne fonctionne pas lorsque vous devez utiliser -objectAtIndex:. Je ne pense pas qu'il y ait une bonne solution pour vous. -valueForKeyPath: ne résoudrait pas non plus le problème des erreurs d'exécution. Si vous voulez vraiment un moyen simple de faire cela, vous pouvez écrire votre propre version de -valueForKeyPath: (appelez ça quelque chose d'autre) qui fournit une syntaxe pour spécifier un -objectAtIndex: au lieu d'une clé, et qui effectue les vérifications dynamiques appropriées pour assurer l'objet répond réellement à la méthode en question.

+0

Je créerai moi-même 'valueForKeyPath'. Merci :) – Gustav

0

Si vous voulez plus facile à lire le code, vous pouvez diviser la ligne en plusieurs lignes comme celui-ci

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

et ainsi de suite.

0

Je pense que vous pouvez créer un tableau qui contiendra le "chemin" complet de votre objet. La seule chose, vous devez stocker vos index en quelque sorte, peut-être dans NSNumber, dans ce cas vous ne pouvez pas utiliser les objets NSNumber comme clés dans vos dictionnaires. Ensuite, créez une méthode qui retournera l'objet nécessaire pour ce "chemin" donné. smth like

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

Ceci est juste une idée, mais j'espère que vous comprenez ce que je veux dire. Et comme Kevin l'a mentionné plus haut, si vous n'avez pas d'index, vous pouvez utiliser le codage de valeurs-clés.

0

Je ne sais pas si cela peut vous convenir, mais vous pouvez aussi essayer de bloquer, je les trouve toujours très pratique. Au moins, ils ont rendu le code beaucoup plus lisible.

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]; 
Questions connexes