Tri d'un tableau de dico sur une clé localisée

LeChatNoirLeChatNoir Membre, Modérateur
Salut,

Bon je bute sur localizedCaseInsensitiveCompare:...
J'ai un tableau de NSDictionary.
Dans ce NSDictionary, j'ai une propriété "pays" (NSString).

Dans mon modèle, les pays sont stockés en français.
Mais quand j'affiche les pays, je fais un NSLocalizeString et il va me chercher la traduction dans mon localizable.strings.

Mais.... Afrique du Sud, in english, c'est South Africa. Vous voyez le pb : l'ordre change radicalement.

Je comptais donc faire un tri beta tel que :
<br />NSSortDescriptor *paysDescriptor =[[[NSSortDescriptor alloc] initWithKey:@&quot;pays&quot; ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)] autorelease];<br />self.sortedArrayTree = [monArrayUnsorted sortedArrayUsingDescriptors:[NSArray arrayWithObjects:paysDescriptor, nil]];<br />


Mais ça fonctionne pas !  B)
Alors forcément, je me demande s'il va bien chercher les localisations dans mon fichier...
Bref, je sèche...
J'ai fait un truc comme ça pour m'en sortir mais bon, c'est un peu moche et surtout, j'altère mon tableau initial....

for (NSMutableDictionary * tmpDict in monArrayUnsorted)
[tmpDict setValue:NSLocalizedString([tmpDict objectForKey:kSitePays],@";") forKey:kSitePays];

et ensuite je tri et là , no problemo...

C'est grave doc ? Y a un truc que j'ai pas pigé ?
Merci !


Réponses

  • AliGatorAliGator Membre, Modérateur
    mars 2011 modifié #2
    Non, localizedCaseInsensitiveCompare ne va pas du tout chercher les traductions dans tes fichiers localisés.
    Le "localized" dans le nom de la méthode c'est pour dire que la comparaison prend en compte la NSLocale pour la comparaison. Ca veut dire que si tu utilises une NSLocale du genre langue de pays nordique, "o" et "à¸" auront la même valeur au sens de la comparaison des chaà®nes  (NSOrderedSame), alors que pour une NSLocale française ils seront différents, par exemple le "o" sera considéré comme à  classer avant le "à¸" (NSOrderedAscending)

    Si tu veux aller chercher les traductions et trier selon ces traductions, il faut utiliser un NSSortDescriptor qui n'utilise pas juste le KVC mais utilise une fonction de comparaison qui va chercher explicitement la traduction dans le fichier de traductions.
    Par exemple avec iOS4 et les blocks, tu peux faire :
    self.sortedArrayTree = [monArrayUnsorted sortedArrayUsingComparator: ^(id obj1, id obj2) {<br />&nbsp; NSString* loc1 = NSLocalizedString(obj1,@&quot;&quot;);<br />&nbsp; NSString* loc2 = NSLocalizedString(obj2,@&quot;&quot;);<br />&nbsp; return [loc1 compare:loc2];<br />}];
    
    Sinon (ou pour iOS <4.0 et les runtimes qui ne supportent pas les blocks) tu peux utiliser "sortedArrayUsingFunction:context:" et utiliser une fonction C pour la comparaison, ou tu peux encore plus proprement et plus joliment créer une catégorie de NSString qui rajoute une méthode du genre "compareUsingLocalization:", puis utiliser ce selector pour ton tri.

    Dernière solution, tu utilises un NSSortDescriptor classique avec juste le KVC, mais pas sur la clé "pays" mais sur une clé qu'on va appeler "localizedCountry". Clé qui en fait est calculée, c'est à  dire que tu as juste à  prévoir un accesseur (readonly suffit) : donc tu rajoutes juste une méthode dans ta classe :
    -(NSString*)localizedCountry { return NSLocalizedString(self.pays,@&quot;&quot;); }
    
    sauf que bon si les éléments de ton tableau " éléments qui contiennent entre autres ta clé pays " ne sont pas des classes perso mais genre des NSDictionary... bah tu vas un peu avoir du mal à  rajouter proprement cette méthode localizedCountry (d'où l'intérêt d'avoir prévu/conçu un modèle métier propre lors de l'architecture logicielle de ton appli, au passage)
  • LeChatNoirLeChatNoir Membre, Modérateur
    17:26 modifié #3
    ah ouais, classe les blocks !
    J'étais parti sur le fonction C mais c'est plutot séduisant.
    Et comme mon appli est iOS4 mini...
    Alors on dit quoi ?
    Merci Ali 
  • AliGatorAliGator Membre, Modérateur
    17:26 modifié #4
    PS : M'étais gourré (un petit copier-coller un peu rapide de la signature du block) dans le code au dessus, il fallait bien sûr écrire [tt]^(id obj1, id obj2){ ... }[/tt] pour écrire le block qu'on passe en paramètre à  [tt]sortedArrayUsingComparator:[/tt]
Connectez-vous ou Inscrivez-vous pour répondre.