NSOutlineView Auswahl beibehalten [Erledigt]

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • NSOutlineView Auswahl beibehalten [Erledigt]

    Ich versuche momentan eine Liste von Einträgen mit Untereinträgen in einem NSOutlineView anzuzeigen, was auch funktioniert, und regelmässig zu aktualisieren.
    Und bei der Aktualisierung hab ich das Problem, dass sich die Auswahl unter unter Umständen ändert. Es bleiben immer die Zeilen ausgewählt, auch wenn der Eintrag seine Position ändert. (z.B. wenn ein Eintrag hinzukommt oder entfernt wird)

    Nun bin ich auf die naheliegende Idee gekommen, die ausgewählten Objekte in outlineViewSelectionDidChange in ein Array zu schreiben und nach dem aktualisieren wieder zu selektieren, funktioniert ebenfalls.
    Allerdings kommt es teilweise vor, wenn ich während der Aktualisierung Einträge auf- oder zuklappe, dass es zu einem Exception kommt (nicht immer der gleiche).

    Die Aktualisierung wird in einem gesonderten Thread durchgeführt. Die Wiederherstellung der Selektion hatte einmal im gleichen und auch schon testweise im Main-Thread.


    Das ist der Code zum wiederherstellen der Selektion:

    Quellcode

    1. - (void)restoreSelection {
    2. if (selectedKeys && !isRestoring) {
    3. isRestoring = YES;
    4. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    5. NSMutableIndexSet *selRowIndexes = [NSMutableIndexSet indexSet];
    6. for (id item in selectedKeys) {
    7. [selRowIndexes addIndex:[myOutlineView rowForItem:item]];
    8. }
    9. [myOutlineView selectRowIndexes:selRowIndexes byExtendingSelection:NO];
    10. [pool drain];
    11. isRestoring = NO;
    12. }
    13. }
    Alles anzeigen


    Und da ich mit meinem Latein am Ende bin, meine Frage: Wie ist es möglich die Auswahl beizubehalten, wenn sich der Inhalt der Liste ändert, ohne dass es zu Exceptions kommt?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von RJZ ()

  • Ich hab es bereits probiert die Selektion im Main-Thread zu ändern, das Problem besteht trotzdem.

    EDIT:
    Die Aktualisierung wird im nebenläufigen Thread durchgeführt. Die Daten kommen aus einem Array, dieses ersetze ich durch ein anderes und führe dann [myOutlineView reloadData] aus.
  • Meine Antwort bezog sich auf Michael.

    Das ist der Code welcher im nebenläufigen Thread ausgeführt wird und die Aktualisierung vornimmt:

    Quellcode

    1. oldKeyList = showedKeyList;
    2. showedKeyList = [pubKeyList copy];
    3. [oldKeyList release];
    4. [myOutlineView reloadData];

    Bei den Key-Listen handelt es sich um NSArrays.
  • Hab ein ähnliches Problem kürzlich gehabt:

    Quellcode

    1. -(void)updateSelection:(NSIndexSet*)newIndexes
    2. {
    3. [myOutlineView selectRowIndexes:selRowIndexes byExtendingSelection:NO];
    4. }
    5. - (void)restoreSelection {
    6. if (selectedKeys && !isRestoring) {
    7. isRestoring = YES;
    8. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    9. NSMutableIndexSet *selRowIndexes = [NSMutableIndexSet indexSet];
    10. for (id item in selectedKeys) {
    11. [selRowIndexes addIndex:[myOutlineView rowForItem:item]];
    12. }
    13. [self performSelectorOnMainThread:@"selector(updateSelection:) withObject:selRowIndexes waitUntilDone:NO ];
    14. [pool drain];
    15. isRestoring = NO;
    16. }
    17. }
    Alles anzeigen

    Was für Objekte aktualisierst Du denn? Eine eigene Klasse? Löschst Du alle Objekte in jedem Aktualisierungsdurchlauf und baust Deinen Datenbaum neu auf?
    Vlt. ist es ja möglich, vorhandene Objekte zu behalten und lediglich deren Attribute zu aktualisieren. In diesem Fall kannst Du einen Bindingscontroller benutzen und die Selektion bleibt erhalten, ganz ohne Deinen Code.
  • Ja, bei den Objekten im Array handelt es sich um Objekte einer eigenen Klasse mit Unterobjekten.
    Ich lösche nur die Objekte, welche es nicht mehr gibt, alle anderen bleiben erhalten. Wenn möglich werden nur die Attribute aktualisiert.

    Wie funktioniert das mit einem Bindingscontroller? Ich verwende ein eigene DataSource Klasse.

    Edit:
    Ich hab den Code von dir getestet, es funktioniert leider ebenfalls nicht.

    Edit2:
    In der Zeile

    Quellcode

    1. [myOutlineView selectRowIndexes:selRowIndexes byExtendingSelection:NO];
    bekomme ich teilweise diese Fehlermeldung
    *** -[NSCFArray insertObject:atIndex:]: attempt to insert nil

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von RJZ ()

  • Poste mal das Log beim Crash. Allerdings musst Du bedenken, dass sich die Auswahl ändert, wenn Du das OV auf und zuklappst, ich vermute, da kommt es zu race-conditions.
    Zum BindingsController:
    Nimm einen NSTreeController und trage im IB die entspr. Modellkeys (für die children-Eigenschaft) ein. Dann bindest Du die Spalte Deines OV daran.Hier gibts Doku und Beispielcode.
  • RJZ schrieb:

    Ich bekomme den Fehler auch wenn ich

    Quellcode

    1. [myOutlineView reloadData];
    mit performSelectorOnMainThread in den Main-Thread verlagere.

    Dann hast du einen weiteren Fehler.

    Was machst du noch in dem anderen Thread?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Im Aktualisierungs-Thread schaue ich welche der Informationen, auf denen meine Objekte basieren, sich geändert haben und passe die Objekte entsprechend an.
    Dann führe ich das reloadData aus und zum Schluss stelle ich die Selektion wieder her.
  • RJZ schrieb:

    Im Aktualisierungs-Thread schaue ich welche der Informationen, auf denen meine Objekte basieren, sich geändert haben und passe die Objekte entsprechend an.
    Dann führe ich das reloadData aus und zum Schluss stelle ich die Selektion wieder her.

    Die Selektionsänderung machst du auch im zweiten Thread?

    Anders gefragt: Taucht in deinem zweiten Thread irgendeine Instanz irgendeiner Klasse auf, die zum AppKit gehört?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RJZ schrieb:

    Ja und ja.
    Allerdings hatte ich es auch schon versucht mit performSelectorOnMainThread in den Main-Thread zu verlagern.

    Beides gleichzeitig? Aktualisierung und Selektion?

    Das ganze sieht ja extreem nach einem Threading-Problem auf.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?