97 votes

Récupérer un objet à partir d'un NSSet

Si vous ne pouvez pas obtenir un objet avec objectAtIndex : à partir d'un NSSet, alors comment récupérer des objets ?

1 votes

[[nsSetObjects allObjects] objectAtIndex: anyInteger]

144voto

Matthew Flaschen Points 131723

Il existe plusieurs cas d'utilisation d'un ensemble. Vous pourriez énumérer à travers (par exemple avec enumerateObjectsUsingBlock ou NSFastEnumeration), appelez containsObject pour tester l'adhésion, utilisez anyObject pour obtenir un membre (non aléatoire), ou le convertir en un tableau (sans ordre particulier) avec allObjects .

Un ensemble est approprié lorsque vous ne voulez pas de doublons, que vous ne vous souciez pas de l'ordre et que vous voulez un test d'appartenance rapide.

7 votes

Vous pouvez également rechercher un objet connu par un doublon potentiel en envoyant au jeu un member: message. S'il renvoie nil Si elle retourne un pointeur d'objet, alors le pointeur qu'elle renvoie est celui de l'objet déjà présent dans l'ensemble. Les objets de l'ensemble doivent implémenter hash y isEqual: pour que cela soit utile.

0 votes

@PeterHosey Je ne pense pas que hash besoins à mettre en œuvre ; cela irait beaucoup plus vite si vous le faisiez.

2 votes

@fumoboy007 : Pour le stockage dans un ensemble ou l'utilisation comme clé dans un dictionnaire, oui c'est le cas. D'après la documentation de hash dans le protocole NSObject : " Si deux objets sont égaux (comme déterminé par le protocole isEqual: ), ils doivent avoir la même valeur de hachage". Actuellement, les implémentations de NSObject de hash y isEqual: utiliser l'identité de l'objet (adresse). Si vous remplacez isEqual: vous mettez en place la possibilité d'objets qui ne sont pas identiques mais qui sont égaux - ce qui, si vous ne remplacez pas également l'option hash , auront toujours des hachages différents. Cela viole l'exigence selon laquelle des objets égaux ont des hachages égaux.

32voto

NSSet n'a pas de méthode objectAtIndex :

Essayez d'appeler allObjects qui renvoie un NSArray de tous les objets.

0 votes

Savez-vous si le tableau retourné est ordonné ? En d'autres termes, si j'ajoute des objets à l'ensemble en utilisant "setByAddingObject", et que j'ai utilisé "allObjects", les éléments du tableau sont-ils ? ordonnés dans l'ordre où j'ai ajouté les objets ?

0 votes

Il suffit de trier le tableau résultant avec un NSSortPredicate et tout ira bien.

0 votes

Si vous n'êtes intéressé que par un seul objet spécifique, il vaut mieux utiliser l'approche filtréeSetUsingPredicate.

17voto

Il est possible d'utiliser filteredSetUsingPredicate si vous disposez d'une sorte d'identifiant unique pour sélectionner l'objet dont vous avez besoin.

Créez d'abord le prédicat (en supposant que votre identifiant unique dans l'objet s'appelle "identifier" et qu'il s'agit d'une NSString) :

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];

Et ensuite choisir l'objet en utilisant le prédicat :

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;

14voto

krischu Points 84

NSArray *myArray = [myNSSet allObjects];

MyObject *object = [myArray objectAtIndex:(NSUInteger *)]

remplacez NSUInteger par l'index de l'objet souhaité.

1 votes

Devrait être : MyObject *object = [myArray objectAtIndex :(NSUInteger *)]

6voto

horseshoe7 Points 707

NSSet utilise la méthode isEqual : (que les objets que vous placez dans cet ensemble doivent surcharger, en plus de la méthode hash) pour déterminer si un objet se trouve à l'intérieur de celui-ci.

Ainsi, par exemple, si vous avez un modèle de données qui définit son unicité par une valeur d'identification (disons que la propriété est :

@property NSUInteger objectID;

alors vous implémenteriez isEqual : en tant que

- (BOOL)isEqual:(id)object
{
  return (self.objectID == [object objectID]);
}

et vous pourriez implémenter le hachage :

- (NSUInteger)hash
{
 return self.objectID;  // to be honest, I just do what Apple tells me to here
                       // because I've forgotten how Sets are implemented under the hood
}

Ensuite, vous pouvez obtenir un objet avec cet ID (ainsi que vérifier s'il est dans le NSSet) avec :

MyObject *testObject = [[MyObject alloc] init];
testObject.objectID = 5; // for example.  

// I presume your object has more properties which you don't need to set here 
// because it's objectID that defines uniqueness (see isEqual: above)

MyObject *existingObject = [mySet member: testObject];

// now you've either got it or existingObject is nil

Mais oui, la seule façon d'obtenir quelque chose d'un NSSet est de considérer ce qui définit son unicité en premier lieu.

Je n'ai pas testé ce qui est plus rapide, mais j'évite d'utiliser l'énumération parce que cela pourrait être linéaire alors que l'utilisation de la méthode member : serait beaucoup plus rapide. C'est l'une des raisons pour lesquelles je préfère l'utilisation de NSSet plutôt que de NSArray.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X