La différence entre NSIndexSet et NSArray c'est quoi au juste...

GercofisGercofis Membre
22:36 modifié dans API AppKit #1
Beaucoup mal a comprendre le sens de NSIndexSet
J'ai lu un peu tout sur ce sujet...

J'en ai déduit que NSIndexSet est une suite/tableau d'index pointant sur les lignes d'un tableau.

Un exemple montrant un parallèle entre l'un et l'autre ?

:o

Réponses

  • Eddy58Eddy58 Membre
    22:36 modifié #2
    NSIndexSet est une classe pour représenter et stocker les indexes d'objets divers, par exemple pour récupérer ou régler la sélection d'une NSTableView. :)

    Le code suivant sélectionnera dans ta tableview 5 lignes à  partir de la 3e ligne :
    [tt]
    [maTableView selectRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3,5)] byExtendingSelection:YES];
    [/tt]

    Les utilisations sont multiples, dans un cas pratique tu peux vouloir par exemple récupérer tout les objets de ton modèle, par exemple des objets dans un NSMutableArray, qui sont associés à  la sélection de ta tableview. La méthode selectedRowIndexes te donne l'index de la sélection, ensuite tu peux récupérer un array des objets en rapport avec la sélection avec la méthode objectsAtIndexes.
  • GercofisGercofis Membre
    22:36 modifié #3
    Si tu me dis comment je complète correctement cette le délégate du drag suivant:
    - (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard;<br />{<br />	<br />	NSLog(@&quot;writeRowsWithIndexes:&quot;);<br />	NSArray *typesArray = [NSArray arrayWithObjects:CopiedRowsType, MovedRowsType,CoreDataDragType,nil];<br />	// declare our own pasteboard types for moving and copying<br /> 	[pboard declareTypes:typesArray owner:self];<br /><br />&nbsp; &nbsp; // add rows for move and copy to pasteboard<br />	//[pboard setPropertyList:[self dragRearrangeRowsForWritingToPBoard:rowIndexes] forType:MovedRowsType];<br />	//[pboard setPropertyList:[self dragCopyRowsForWritingToPBoard:rowIndexes] forType:CopiedRowsType];*/<br />	<br />	[pboard setData:rowIndexes forType:CoreDataDragType];// c&#39;est ici que ça ne doit pas aller<br />&nbsp; &nbsp; <br />	return YES;<br />}<br />
    

  • Eddy58Eddy58 Membre
    février 2006 modifié #4
    Alors là , malheureusement, je suis loin d'être assez expérimenté en drag&drop et CoreData pour résoudre ton problème.
    La seule indication que je puisse te donner, c'est que le setData attend une NSData, qu'il faut générer en allant chercher dans ta couche modèle les données correspondant à  l'index du NSIndexSet fourni. :o

    [EDIT]
    Bon, j'ai regardé un peu à  quoi ressemble le code de drag de l'exemple Bookmarks.
    [tt]
    // create new array of selected rows for remote drop
        // could do deferred provision, but keep it direct for clarity
    NSMutableArray *rowCopies = [NSMutableArray arrayWithCapacity:[rows count]];   
    NSEnumerator *rowEnumerator = [rows objectEnumerator];
    NSNumber *idx;
    while (idx = [rowEnumerator nextObject])
    {
    [rowCopies addObject:self arrangedObjects] objectAtIndex:[idx intValue];
    }
    // setPropertyList works here because we're using dictionaries, strings,
    // and dates; otherwise, archive collection to NSData...
    [pboard setPropertyList:rowCopies forType:CopiedRowsType];

    return YES;
    [/tt]
    Je pense qu'il faut que tu fasses quelque chose dans le genre en allant chercher les objets concernés par le NSIndexSet via ton NSManagedObject.
  • aranaudaranaud Membre
    22:36 modifié #5
    NSIndexSet est une classe pour représenter et stocker les indexes d'objets divers, par exemple pour récupérer ou régler la sélection d'une NSTableView.


    Donc si j'ai bien compris, sa ne donne pas le id d'un objet mais juste sa position relative dans un tableau ou une liste.
  • AliGatorAliGator Membre, Modérateur
    22:36 modifié #6
    Oui, d'où le nom de "index set", ensemble d'indexs quoi.

    Un indexSet peut par exemple être composé des indexes {2,3,6,8}, et si tu utilises cet NSIndexSet sur un tableau T pour lui demander les objets à  ces indexes, il te retournera le sous-tableau S composé du 2e, 3e, 6e et 8e élément du tableau T.
    Comme tout ensemble (Set) qui se respecte, il ne peut contenir qu'une seule fois chaque index (on ne peut pas avoir deux fois l'index 3 par exemple)

    NSString* obj0 = @&quot;exemple d&#39;objet&quot;;<br />NSTextField* obj1 = ...<br />id obj2 = ...<br />NSDictionary* obj3 = ...<br /><br /><br />NSArray* T = [NSArray arrayWithObjects:obj0,obj1,obj2,obj3,obj4,obj5,obj6,obj7,obj8,obj9,nil];<br /><br />NSMutableIndexSet mySet = [NSMutableIndexSet indexSet];<br />[mySet addIndex:2];<br />[mySet addIndex:3];<br />[mySet addIndex:6];<br />[mySet addIndex:8];<br />// ce ne sont que des indexes de position dans un tableau<br /><br />// ici on récupère les objets correspondant à  ces indexes dans le tableau T<br />NSArray* S = [T objectsAtIndexes:mySet];<br />// S va contenir les objets obj2,obj3,obj6 et obj8
    
  • aranaudaranaud Membre
    22:36 modifié #7
    Ok AliGator, donc dans ton exemple. Si je supprime obj1 par exemple, est que l'index 8 reste toujours l'objet obj8 ou devient-il comme je le pense obj9 ?
  • AliGatorAliGator Membre, Modérateur
    22:36 modifié #8
    si tu supprimes l'objet obj1 de T avant de demander objectsAtIndexes, l'index 8 correspondra à  obj9 en effet.
    // en supposant que T et mySet sont les mêmes que mon code d&#39;exemple plus haut<br /><br />NSArray* S1 = [T objectsAtIndexes:mySet]; // obj2, obj3, obj6, obj8<br />[T removeObjectAtIndex:1]; // on enlève l&#39;objet à  l&#39;index 1 (c&#39;est à  dire obj1 en l&#39;occurence)<br />NSArray* S2 = [T objectsAtIndexes:mySet]; // obj3, obj4, obj7, obj9 maintenant que tout a été décalé.
    
  • tabliertablier Membre
    octobre 2009 modifié #9
    Est-ce que ça ne permettrait pas aussi de créer des 'set' arrangés différemment que dans le NSArray d'origine: {obj5, obj2, obj11, obj1.. etc} ?
  • AliGatorAliGator Membre, Modérateur
    octobre 2009 modifié #10
    Bon au passage la petites astuce car j'en ai marre de devoir faire 50 lignes pour créer un IndexSet, donc déjà  une catégorie pour en créer un plus facilement (pas testé, code tapé direct dans le forum, mais ça devrait être pas loin) :
    // Catégorie de NSIndexSet parce que c&#39;est lourd à  en créer un sinon<br />@interface NSIndexSet (EasyConstructor)<br />-(id)initWithIndexes:(int)firstIndex, ... NS_REQUIRES_NIL_TERMINATION;<br />@end<br /><br />@implementation NSIndexSet (EasyConstructor)<br />-(id)initWithIndexes:(int)firstIndex, ...<br />{<br />&nbsp; NSMutableIndexSet* s = [NSMutableIndexSet indexSetWithIndex:firstIndex];<br />&nbsp; NSUInteger idx;<br />&nbsp; va_list ap;<br />&nbsp; va_start(ap,firstItem);<br />&nbsp; while(nil != (idx = va_arg(ap,int))) {<br />&nbsp; &nbsp; [s addIndex:idx];<br />&nbsp; }<br />&nbsp; va_end(ap);<br />&nbsp; <br />&nbsp; [self initWithIndexSet:s];<br />&nbsp; return self;<br />}<br />@end
    
    Petit inconvénient de la façon dont j'ai fait mon constructeur : il s'arrête de parser les arguments quand il rencontre le premier NIL (un peu comme arrayWithObjects et consoeurs)... Oui mais 0 est interprété comme le pointeur NULL donc comme nil. Donc si vous voulez créer un NSIndexSet contenant l'index zéro à  l'aide de cette méthode, il faut mettre cette valeur de zéro comme premier argument
    - [tt]initWithIndexes:0,0[/tt] = [tt]initWithIndexes:0,nil[/tt] = indexSet avec l'index 0 uniquement
    - [tt]initWithIndexes:1,0[/tt] = [tt]initWithIndexes:1,nil[/tt] = indexSet avec l'index 1 uniquement
    - [tt]initWithIndexes:0,2,0[/tt] = [tt]initWithIndexes:0,2,nil[/tt] = indexSet avec les indexes 0 et 2.
    - [tt]initWithIndexes:2,0,3,nil[/tt] = [tt]initWithIndexes:2,nil,3,nil[/tt] = [tt]initWithIndexes:2,nil[/tt] = indexSet avec l'index 2 uniquement (piège) !

    Mais bon ça permet en une seule ligne de créer un NSIndexSet avec plein d'index dedans (je suis étonné qu'il n'y ait pas déjà  une méthode du genre d'ailleurs), et cette petite limitation d'être obligé de mettre l'index 0 en premier si on souhaite que l'indexSet le contienne n'est pas embêtante puisqu'un NSIndexSet n'est pas ordonné.



    Sinon pour ta question sur le réarrangement des éléments, ce n'est pas si simple, parce qu'un NSIndexSet est un set = un ensemble. Donc par définition un ensemble n'a non seulement que des éléments uniques, mais n'a pas non plus de notion d'ordre entre ses éléments.

    Autrement dit un NSIndexSet avec les éléments {2,3,5,6} et un set avec les éléments {3,6,5,2} sont les mêmes ensembles.

    D'ailleurs fais gaffe à  ton vocabulaire pour ne pas tout confondre : "créer des sets arrangés différemment" ça n'a justement pas de sens... parce qu'un set (un ensemble) ne peut être arrangé, par définition, ses éléments n'ayant pas d'ordre. Un NSArray par contre, non seulement peut contenir des éléments en doublon, mais est de plus ordonné. C'est pour ça que tu vois des méthodes comme [tt]- (void)exchangeObjectAtIndex:(NSUInteger)idx1 withObjectAtIndex:(NSUInteger)idx2[/tt] dans la doc de NSMutableArray ;)
Connectez-vous ou Inscrivez-vous pour répondre.