2010-12-23 8 views
0

J'ai inclus un espace réservé [NSNull null] dans mon tableau de sources de données combobox afin que je puisse permettre à l'utilisateur de sélectionner "none" sans réellement stocker un objet vide. Le problème est que lorsqu'un objet réel est ajouté au tableau de source de données, je dois trier le tableau:comment trier un NSMutableArray qui contient une instance de NSNull

[self.mutableArrayOfStrings sortUsingSelector:@selector(caseInsensitiveCompare:)]; 

Cette ligne produit un SIGKILL.

J'ai le même problème avec le tableau compagnon de NSManagedObject, qui a également un espace réservé NSNull:

NSSortDescriptor *sortDescriptorName = [[NSSortDescriptor alloc] initWithKey:@“name” ascending:YES selector:@selector(caseInsensitiveCompare:)]; 
NSArray *sortDescriptorsNames = [[NSArray alloc] initWithObjects: sortDescriptorName, nil]; 
[self.mutableArrayOfMOs sortUsingDescriptors:sortDescriptorsNames]; 

Si mutableArrayOfMOs contient un objet NSNull, cette ligne produit également un SIGKILL.

Bien sûr, je pourrais copier les objets non nuls dans un tableau séparé, le trier, réinsérer l'objet nul et l'assigner à la propriété du tableau - mais cela encombrerait mon code. Ne devrait-il pas y avoir des moyens de tri qui ne s'étouffent pas sur NSNull? Après tout, Apple a fourni NSNull explicitement pour nous permettre de l'inclure dans les tableaux.

Répondre

4

Le problème principal est de savoir ce que NSNull peut faire comme -est-il avant ou après un élément connu? - il n'y a pas de réponse générale - donc Apple ne peut pas une méthode d'usage général.

Dans votre cas, vous triez par sortUsingDescriptors - cela prend la propriété "nom" des objets dans le tableau - quelle est la valeur de la propriété "nom" pour NSNull? Donc, en utilisant sortUsingDescriptors, vous devez supprimer NSNull comme vous le décrivez. Si vous souhaitez conserver le NSNull dans le tableau, vous pouvez essayer de trier d'une autre manière - sortUsingFunction: context: vous permettra d'écrire une fonction de comparaison qui peut gérer NSNull. Le code Apple doit uniquement traiter des objets connus et non de ce qu'ils contiennent.

+4

Ou encore mieux, vous pouvez trier en utilisant 'sortUsingComparator:', qui prend un bloc 'NSComparator' et vous évite d'avoir à ajouter une fonction hors-lieu au milieu de votre code. –

+0

Merci pour votre aide! Je vois à partir de la réponse de Mark que je courais au-dessus des comparateurs. En ce qui concerne les solutions, la suggestion de itaiferber semblait plus facile, donc je l'ai essayé en premier. Je posterai le résultat en tant que réponse séparée. La suggestion de Mark fournirait plus de flexibilité sur la directionnalité, selon ce lien: http://thoughts.digital-transience.com/2009/03/sorting-nsarrays/comment-page-1/ – Wienke

0

Voici ce que je suis venu avec la suite de itaiferber de suggestion (et l'utilisation de la Fondation des types de données d'Apple référence):

Je mets cela dans le fichier h:

typedef NSComparisonResult (^NSComparator)(id string1, id string2); 

I ajouté cette méthode:

- (NSArray *) sortNullsToTopInStringArray:(NSArray *)array { 

NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id string1, id string2) {  

    // First test for null object. It should go to top (beginning) of list. 
    if ([string1 class] == [NSNull class]) 
     return (NSComparisonResult)NSOrderedAscending; 

    if ([string2 class] == [NSNull class]) 
     return (NSComparisonResult)NSOrderedDescending; 

    // For non-null strings, use regular NSString compare method, and wrap it in NSComparisonResult. 
    switch ([string1 caseInsensitiveCompare:string2]) { 
     case NSOrderedAscending: 
      return (NSComparisonResult)NSOrderedAscending; 
     case NSOrderedSame: 
      return (NSComparisonResult)NSOrderedSame; 
     case NSOrderedDescending: 
      return (NSComparisonResult)NSOrderedDescending; 
     default: 
      return (NSComparisonResult)NSOrderedAscending; 
    } 

}]; 

return sortedArray; 
} 

et utilisé ici:

NSArray *sortedArray = [self sortNullsToTopInStringArray:self.mutableArrayOfStrings]; 
NSMutableArray *sortedMutableArray = [sortedArray mutableCopy]; 
self.mutableArrayOfStrings = sortedMutableArray; 
[sortedMutableArray release]; 

Le tri des objets NSManagedObjects peut être effectué de la même manière, mais je dois fournir des méthodes différentes pour chaque type d'entité, afin d'extraire les chaînes.

Merci encore à Mark et itaiferber.

Questions connexes