2009-06-21 6 views
2

Dans mon projet, j'utilise une propriété propertyList pour gérer les données. le fichier plist est nommé "DataBase.plist". la racine pour DataBase.plist est un dictionnaire qui contient 5 dictionnaires comme des éléments enfants ... maintenant le sous-dictionnaire contient 4 chaînes dont l'une est toujours une adresse web avec la clé "URL" (sans les guillemets) .... i « m exécutant le code suivant pour extraire la valeur de cette clé URL, mais il ne fonctionne pas sur ..Lecture des clés NSDictionary à partir des listes de propriétés

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
NSString *URLforAll = [[NSString alloc] init]; 
for (id key in rootDict) 
{ 
    if(key == rowString) 
    { 
     NSDictionary *dict = [rootDict objectForKey:key]; 
     URLforAll = [dict objectForKey:@"URL"]; 
    } 
} 

la rowstring est une chaîne dont la valeur est la même que le texte dans la cellule sélectionnée (je l'ai testé, c'est précis). S'il vous plaît aidez-moi si vous le pouvez .... Je serai reconnaissant

+0

Cette question pourrait être nommée plus clairement, peut-être "Lecture des clés NSDictionary d'un fichier de liste de propriétés". Il ne voit vraiment rien à voir avec le codage à valeur-clé (regardez-le) et certainement rien de spécifique à l'iPhone. Retaillé en conséquence. –

Répondre

3

Essayez d'utiliser [key isEqualToString: rowString] au lieu de comparer directement la clé et rowString en utilisant ==. Je pense que == compare les valeurs de pointeur de l'objet, qui ne seront pas égales même si les chaînes correspondent.

Aussi - juste en aparté, vous n'avez pas besoin d'initialiser URLforAll avant de le définir. Lorsque vous le définissez égal à [dict objectForKey:@"URL"], vous perdez le pointeur vers l'objet que vous avez déjà créé et il sera divulgué. Au lieu de cela, dites simplement NSString *URLforAll = nil; ou créer une nouvelle chaîne et autorelease pour que l'objet sera nettoyé automatiquement:

NSString * URLforAll = [[[NSString alloc] init] autorelease]; 
+1

Toutes les bonnes suggestions. Vous avez raison: == compare les adresses mémoire (pointeurs). Contrairement à C++, Objective-C ne supporte pas les opérateurs surchargés. En fait, cette même erreur infeste même les développeurs Java. Je pourrais éviter de créer d'abord un objet autoreleased - si URLforAll (mal nommé) est nul après la boucle for, créez un objet alors. Il ne devrait probablement être autoeleased si elle est retournée d'une méthode. –

+0

En premier lieu - merci beaucoup d'avoir aidé - -equilibreToString a fonctionné parfaitement .... ... .... et Après le code ci-dessus, j'ajoute [URLforAll]; au lieu d'utiliser [[[NSSTring alloc] init] autorelease]; Est-ce que la mémoire est encore fuit ... si cela s'il vous plaît dites-moi comment ... s'il vous plaît dites-moi ... et aussi je lis quelque part que l'utilisation autorelease pour iphone n'est pas suggéré .... et sur le nom URLofAll it a été changé pour la question ... merci un million pour l'aide – valiantb

+1

Vous n'avez pas besoin d'allouer/init URLforALl du tout. Il suffit de l'initialiser à zéro. La méthode objectForKey: du dictionnaire retournera vous donner un objet autoreleased. – amrox

2

Vous n'avez pas besoin de boucler dans le dictionnaire. Il suffit de demander pour les données que vous voulez.

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[[NSDictionary alloc] initWithContentsOfFile:path] autorelease]; 
NNSString *URLString = [[rootDict objectForKey:key] objectForKey:@"URL"]; 

// do something or return URLString... 
+0

Un excellent point! Si keyString n'est pas trouvé dans rootDict, il renverra nil et l'objet objectForKey externe n'aura aucun effet. Man, j'adore la gestion des messages de Objective-C à zéro ... :-) –

+0

effectivement en boucle dans le dictionnaire est nécessaire pour le projet en sachant que la chaîne contient toujours une valeur .... Merci beaucoup d'aide .... .. Merci un million – valiantb

+1

'[[[NDDictionary alloc] initWithContentsOfFile: chemin] autorelease]' peut être écrit comme '[NSDictionary dictionaryWithContentsOfFile: chemin]' – user102008

3

De plus, dans votre code:

NSString *URLforAll = [[NSString alloc] init]; 

Cela ne fait jamais les sens. Voici quelques problèmes:

  • Vous avez alloué un objet que vous remplacez ensuite indiscrimanently avec URLforAll = [dict objectForKey:@"URL"];. Vous devrez donc le libérer avant de l'écraser.
  • Il est alloué (c.-à la fin de la boucle, vous « propre » et devrez libérer. Mais [dict objectForKey:@"URL"] retourne un objet qui ne vous appartient pas. Donc, à la fin de la boucle, vous ne sais pas si vous possédez URLforAll ou non.
  • et enfin, [[NSString alloc] init] jamais fait sens parce que vous devez simplement utiliser @"", qui retourne une constante, vide, NSString qui est imperméable à retain/release/autorelease questions.

Dealing également avec le problème isEqualToString, mais en ignorant la meilleure solution d'amrox, le code serait:

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
NSString *URLforAll = @""; 
for (id key in rootDict) { 
     if ([key isEqualToString:rowString]) { 
       NSDictionary *dict = [rootDict objectForKey:key]; 
       URLforAll = [dict objectForKey:@"URL"]; 
     } 
} 
[[URLforAll retain] autorelease]; 
[rootDict release]; 

Notez que objectForKey peut bien renvoyer une référence interne à l'objet qui deviendra invalide lorsque vous relâchez le dictionnaire, d'où la nécessité de conserver l'objet si vous voulez le garder plus longtemps que la durée de vie du dictionnaire.

utilisation de amrox de:

NSString *path = [[NSBundle mainBundle] pathForResource:@"DataBase" ofType:@"plist"]; 
NSDictionary *rootDict = [[NSDictionary alloc] initWithContentsOfFile:path]; 
NSString *URLString = [[rootDict objectForKey:key] objectForKey:@"URL"]; 
[[URLString retain] autorelease]; 
[rootDict release]; 
if (!URLString) { 
    URLString = @""; 
} 

est une meilleure solution, mais vous devriez undertand ce qui ne va pas avec votre solution originale ainsi.

+0

MERCI UN MILLION >>>> JE VOUS AIME – valiantb

Questions connexes