Frage zur Hauptmenü-Gestaltung mit OutlineView

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

  • Anbei das Projekt.
    Was ich damit testen will:
    Ein Objektbaum soll zusammengebaut werden. Dieser Objektbaum besteht aus der Klasse "Baum".
    Im MainController habe ich zwei Actions, die via Buttons neue Objekte, Elemente (implementiert) und Kinder (noch nicht implementiert), anlegen.
    Der Baum soll sich "live" im Fenster wiederspiegeln. Tut er aber über die Actions im MainController nicht.
    Direkt über add: und addChild: - Actions des TreeController (links im Fenster) klappt's wunderbar. Das hilft mir aber nix, ich brauche "vorher gefüllte" Objekte.

    Zweck des Ganzen: ich baue einen Hauptmenübaum, den der TreeController darstellen soll.

    Danke für's angucken!

    No.
  • Ich habe das zum Anlass genommen, mir einen Tag freizunehmen :) und gleich ein umfassendes Tutorial zu schreiben, welches auch dein Problem beinhaltet. Ich lade es gerade hoch. URL gibt es nachher.
    +++
    cocoading.de/Ausgangslage.html

    Es dürfte übrigens für jeden interessant sein, der mit KVO oder Bindings hrumfuhrwerkt.
    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"?
  • n'Abend!
    Oha, das Projekt ist aber ziemlich im Arsch.

    Ich dachte mir schon, daß ich in Deckung gehen muß :rolleyes: Ich habe einiges herumfuhrgewerkt.

    Das Tutorial habe ich mal überflogen. Schaue ich mir nachher noch genauer an.

    // Die bisherigen Autoren abholen und eine mutable Variante aus dem Array machen
    NSMutableArray* authors = [[book authors] mutableCopy];
    // Den neuen Autor einfuegen
    [authors addObject:newPerson];
    // Und das Ganze wieder setzen
    [book setAuthors:authors];

    Na da wäre ich auch in 10 Jahren nicht draufgekommen.

    Im Buch wird erläutert, dass mutable Container als Attribute einer Entität eine gefährliche Sache sind.

    Aha, da muß ich wohl nochmal gaaaanz in Ruhe drüberlesen.

    Ich habe das zum Anlass genommen, mir einen Tag freizunehmen

    Au, danke :) Dafür ist meine Amazon-Rezension endlich online.

    return [[firstName retain] autorelease];

    Die Geschichte muß ich wohl auch nochmal nachlesen.

    TwoOfUs schaue ich mir gleich an.

    LG
    No.
  • Argh, da ist übrigens ein Memory Leak. Gleich verbessern. *schäm*

    Der besondere Getter ist nützlich für Threads. Ansonsten benötigszt du ihn nicht. Er wird aber von Xcode auomatisch so erzeugt. Du musst das auch nicht nachlesen. Im Tutorial findet sich der Hintergrund der Problematik eingehnder erläutert.
    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"?
  • was ich gelernt habe:

    setValue: forKey: geht (natürlich...) genauso für Arrays. Da hätte ich auch drauf kommen müssen...

    NSMutableArray* subtrees = [[selectedTree valueForKey:@"subtrees"] mutableCopy];
    Das Array holst Du Dir, weil ja schon Kindchen drin sein könnten...
    ... oder noch aus einem anderen Grund?
    Dann bearbeitest Du das Array im Controller mit addObject...
    und schickst es KVC-compliant wieder retour
    [selectedTree setValue:subtrees forKey:@"subtrees"];
    und das ist genau das, was ich nicht gemacht hatte.

    Was ich nicht ganz verstehe, weshalb mein Ansatz auch war, das Objekt direkt zu bearbeiten, anstatt eine Kopie zu holen:
    Warum ginge
    Tree* selectedTree = [treeController selection]; // Zeiger auf den ausgewählten Tree
    [selectedTree setNodeName:@"NeuerName" forKey:@"nodename"]; // ändere KVC-compliant
    nicht?

    und, warum
    NSMutableArray* initialTopElements = [[rootTree subtrees] mutableCopy];
    holst Du Dir hier eine Kopie? Steht doch fest, daß noch nix drin ist.

    LG
    No.
  • Du hast inzwischen dich durch alle drei Teile geklickt, nehm ich an?

    Das Grundproblem ist, dass mutable Collections nicht KVC/KVO-compliant sind. Können sie ja auch nicht, weil sie keinen Key besitzen (mal vom Dictionary abgesehen). Daher muss man eines von drei Dingen tun
    * selbst wieder setzen
    * selbst KVO auslösen
    * die to-many-KVC-Methoden benutzen

    Abholen tue ich das immer. Solche Annahmen wie "müsste leer sein" lassen sich in der Wildnis auf Dauer nicht immer halten. ;)
    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"?
  • Wieso in Gottes Namen willst du an die Maus-Routinen?


    Berechtigte Frage, der ich nachgegangen bin. Jetzt weiß ich, warum ich die Maus-Routinen nicht brauche:
    Ich packe einfach
    - (void)outlineViewSelectionDidChange:(NSNotification *)notification;
    ins Delegate des OutlineViews und fertig. Geht super. Die Notification kommt sogar schon beim Programmstart, wenn Menüpunkt 1 ausgewählt wird.
    Kurzum: cool :)

    Wie ich mir jetzt die Info hole, WELCHER Menüpunnkt angeklickt wurde, probiere ich heute. Mal schauen.

    No.
  • Ja, im Buch wird ja sogar mal beispielhaft selbst ein Delegate angelegt ür einen eigenen View: S. 278 ff

    Delegating ist schon eine ungemein praktische Sache, die einem jede Menge Frickeleien in Ableitungen erspart. Du kannst dann ja das übergebene View (Delegate-Methoden bekommen immer den Absender als Parameter) einfach befragen.
    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"?
  • Soda, auch geschafft:
    - (void)outlineViewSelectionDidChange:(NSNotification *)notification{
    NSArray* selectedMenuItem_ = [mainMenuTreeController selectedObjects];
    NSLog([[selectedMenuItem_ objectAtIndex:0] menuItemCode]);

    Faszinierend, wie wenig Zeilen Code man schreiben muss :)

    Habe ich bei "selectedMenuItem_" speicherverwaltungsmäßig was vergessen? Weiß nicht, wo ich hier ein Autorelease unterbringen könnte...?

    Next:
    Einen View eines separaten Nib in einen CustomView des MainMenu.nib laden. Schon wieder nicht untrivial. Der Controller des Nibs soll ein eigener sein.

    No.
  • Nö, das ist so im Ausschnitt korrekt. Du kannst dich allerdings nicht darauf verlassen, dass der Zeiger später noch gültig ist. Du solltest aber noch eine Abfrage machen, ob sich überhaupt ein Element in der Selection befindet, bevor du ein objectAtIndex: machst. if( [selectedMenuItem coount] > 0 ) { …

    Ja, Nibs nachzuladen ist nicht ganz trivial, weil da mit der Speicherverwaltung einiges anders läuft. Lies dir mal die Doku zu NSNib durch. Dort ist es wohl am besten erläutert.
    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"?
  • if( [selectedMenuItem coount] > 0 )

    ist eingefügt.

    Das mit den Nibs ist echt schwer - vor allem Doku darüber zu finden. Nibs in eigene Fenster oder in ein TabView zu laden ist dokumentiert, aber über Nibs in einen CustomView laden finde ich nix.

    Wie ich ein Nib lade weiß ich:
    [NSBundle loadNibNamed:@"SubView" owner:self];
    Das mit dem Files Owner habe ich auch (so halbwegs... ) verstanden.

    Wie ich einen View aus Nib B in den CustomView eines Nib A lade, finde ich beim besten Willen nicht. Ich suche das Gegenstück von NSTabViewItem
    - (void)setView:(NSView *)view
    für einen CustomView.
    Mit
    - (void)addSubview:(NSView *)aView
    bin ich wohl am falschen Dampfer.

    Müde...
    No.
  • Original von norbi
    Das mit den Nibs ist echt schwer - vor allem Doku darüber zu finden. Nibs in eigene Fenster oder in ein TabView zu laden ist dokumentiert, aber über Nibs in einen CustomView laden finde ich nix.

    Also, Nibs lädt man in den Speicher und nirgendwo anders hin. ;)

    Original von norbi
    Ich suche das Gegenstück von NSTabViewItem
    - (void)setView:(NSView *)view
    für einen CustomView.

    NSTabViewItem ist ein "Hilfsobjekt" für NSTabView, d.h. es ist ein für eine spezielle Aufgabe gemachtes Objekt und noch nicht einmal von NSView abgeleitet.

    Original von norbi
    Mit
    - (void)addSubview:(NSView *)aView
    bin ich wohl am falschen Dampfer.

    Nein, hiermit liegst Du goldrichtig. Lade Nib B in den Speicher. Über den Files Owner von Nib B kommst Du an den View, der in die Viewhierarchie von Nib A eingefügt werden soll. Dem View von Nib B musst Du nur die richtigen Koordinaten mitteilen, damit er an der richtigen Position erscheint. In Nib A kannst Du für die Position einen CustomView (einfache NSView Instanz) als Platzhalter verwenden.

    Quellcode

    1. NSRect frameRect = [placeHolder frame];
    2. [viewFromNibB setFrame:frameRect];
    3. [[placeHolder superview] addSubview:viewFromNibB];
    4. [placeHolder removeFromSuperview];
    Michael
  • Noch ein praktischer Tipp: Wenn du in dem "Zusatznib" wiederum deinen Controller zum File's Owner machst, werden genau diejenigen Outlets deines Controllers gesetzt, die du in diesem Nib gesetzt hast. Ich verbinde etwa in einem ähnlichen Fall, ein Outlet in jedem Zusatznib mit "theView" und habe nach dem Laden das enstpechende Outlet gesetzt. Die unverwendeten Ooutlets bleiben unberührt.

    So kann man schnell Verbindungen zwischen verschiedenen Nibs herstellen.
    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"?
  • Wenn man zur Laufzeit ein View hinzufügen will, ist es ein Trick, bereits im Nib einen "leeren" Custom View als Placeholder einzusetzen. Dann kann man zur Laufzeit verschiedene Attribute dieses Placeholder (Gräße, Sizing-Verhalten usw.) einfach übernehmen. So kann man quasi die Nibs durch den Placeholder-View im IB editieren.
    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"?
  • Original von norbi
    Also ist der CustomView in Nib A, nicht der View, der durch den aus Nib B ERSETZT wird, sondern das Bettchen, in (oder auf) das sich der View aus Nib B legt.

    Doch, der Platzhalter-CustomView wird durch den View aus Nib B ersetzt. Von dem Platzhalter wird nur die Position und Größe benutzt, um den View exakt an der gewünschten Stelle zu platzieren. Der Platzhalter wird aus der Viewhierarchie entfernt.

    Original von norbi
    Wofür steht der "placeHolder" in Deinem Codebeispiel?

    Für eine Referenz auf den Platzhalter-CustomView (z.B. ein Outlet).

    Michael