Aktion, wenn UISplitViewController DetailView verlässt

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

  • Aktion, wenn UISplitViewController DetailView verlässt

    Hallo zusammen,

    ich muss eine Aktion durchführen (Rückfrage an den User zum Speichern einer Datei), wenn die DetailView eines UISplitViewControllers verlassen resp. gewechselt wird.

    Im erweiterten Modus - z. B. auf dem iPad - könnte ich dies beim Setzen des neuen Items der DetailView durchführen.

    In der komprimierten iPhone-Sicht ist es ein Problem: die viewWillDisappear:animated:-Methode wird aus irgendeinem Grund beim Wechsel in die MasterView nicht getriggert und ich finde weder eine passende Delegate-Methode, noch eine Möglichkeit, mich in die Aktion des displayModeButtonItem einzuklinken.

    Hat jemand von Euch eine gute Idee, wie ich eine Aktion durchführen kann, wenn ein anderer Item in der MasterView selektiert oder die DetailView verlassen wird? Ich war mir nicht bewusst, dass dieser Setup so ungewöhnlich ist, aber mein Google-fu lässt mich im Stich...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Ich weiß nicht, wie automatisiert der UISplitViewController auf dem iPad mittlerweile ist, aber eigentlich wird der DetailView doch per Code bei einem Wechsel der Selektion im UITableView des MasterViewControllers aktualisiert, oder ist dies nicht mehr der Fall?

    Du könntest also den aktuellen DetailView fragen, ob die Selection gewechselt werden kann oder nicht.

    Auf dem iPhone wird Master/Detail doch über einen NavigationController mit Push des DetailViewControllers realisiert. Daher sollte in dem DetailViewController auch die viewWillDisappear:animated: Methode entsprechend aufgerufen werden, wenn der DetailView verlassen wird. ?(
  • MCDan schrieb:

    Auf dem iPhone wird Master/Detail doch über einen NavigationController mit Push des DetailViewControllers realisiert. Daher sollte in dem DetailViewController auch die viewWillDisappear:animated: Methode entsprechend aufgerufen werden, wenn der DetailView verlassen wird. ?(
    Genau das passiert aber leider nicht. Nun könnte es sein, dass die App in der MasterView beendet wird, die Benutzerabfrage müsste daher unbedingt vor oder beim Verlassen der DetailView erfolgen ... keine Ahnung, warum die genannte Methode nicht aufgerufen wird. Ich bin echt ratlos...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MyMattes () aus folgendem Grund: Fehl-Information, die Methode wird aufgerufen, siehe unten...

  • MyMattes schrieb:

    Genau das passiert aber leider nicht. Nun könnte es sein, dass die App in der MasterView beendet wird, die Benutzerabfrage müsste daher unbedingt vor oder beim Verlassen der DetailView erfolgen ... keine Ahnung, warum die genannte Methode nicht aufgerufen wird. Ich bin echt ratlos...
    Shame on me!

    Doch, die Methode viewWillDisappear:animated: wird aufgerufen ... keine Ahnung, warum ich es übersehen habe, vielleicht zu viele Log-Ausgaben :( Sorry für die Verwirrung.

    Leider musste ich feststellen, dass diese Methode für mein Unterfangen ungeeignet ist, da diese natürlich auch z. B. beim Präsentieren eines weiteren ViewControllers aufgerufen wird. Schwer zu erklären, aber in dem Fall möchte ich keinen Speicher-Dialog haben. Ich werde nach einer Möglichkeit suchen müssen, mich an das "pop" der DetailView zu hängen ... Das ist wenigstens eine vernünftige Knobelarbeit und nicht pures Unverständnis wie beim Ursprungsposting.

    Danke für Eure / Deine Mühe, Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Kurzer Zwischenstand: Die Methoden der Protokolle <UISplitViewControllerDelegate> und <UINavigationControllerDelegate> beinhalten leider keine Methoden, die in dem o. g. Fall aufgerufen werden (schade, zum Zeigen einer View schon).

    Auch ein eigener UINavigationController für die DetailView brachte bisher keinen Erfolg, obwohl ich hier eigentlich den besten Ansatz sehe ... weiteres Forschen wird sich aber etwas gedulden müssen, ich muss morgen wieder Brötchen verdienen :)

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MCDan schrieb:

    Schau Dir mal UINavigationBarDelegate an. Dort gibt es diverse Methoden wenn sich die Items auf dem Navigation Stack ändern (sollen).

    Das war - wie es momentan aussieht - der Schubs in die richtige Richtung: Der Knackpunkt liegt in der Struktur des UISplitViewControllers resp. seiner Unter-Controller. Dieser beinhaltet nämlich zwei geschachtelte UINavigationController, etwa so:
    • UISplitViewController
      • UINavigationController "Master"
        • UIViewController "Master"
        • UINavigationController "Detail"
          • UIViewController "Detail"
    Wenn auf dem iPhone die Detail-View verlassen wird, erfolgt das entsprechende Pop ausschliesslich auf dem Master-NavigationController. Der Detail-NavigationController bekommt davon nichts mit und entsprechende Delegate-Methoden von ihm laufen in's Leere. Deshalb auch meine oben genannten Fehlversuche mit den entsprechenden Protokollen, bei denen ich den Detail-NavigationController benutzt hatte.

    Wenn ich mich jedoch an den Master-NavigationController hänge, bekomme ich das Pop mit. Allerdings habe ich mich konkret entschlossen, dies nicht über eine Delegation zu lösen, sondern ich habe einen angepassten UINavigationController im Storyboard für den Master verdrahtet. Dieser implementiert nur eine Methode (hier wird übrigens erwartungsgemäß der Detail-NavigationController vom Stack entfernt):

    Quellcode

    1. - (UIViewController *)popViewControllerAnimated:(BOOL)animated
    2. {
    3. UIViewController *popVC = [super popViewControllerAnimated:animated];
    4. DebugLog(@"popVC: %@", popVC);
    5. return popVC;
    6. }

    Ich werde hier nun eine NSNotification schicken, die den Detail-ViewController veranlassen wird, die von ihm repräsentierte Datei zu speichern. Dazu komme ich wohl erst Ende der Woche, halte Euch dann aber gerne - bei Interesse - auf dem Laufenden.

    Solange Apple die Struktur des UISplitViewControllers nicht maßgeblich umbaut, sollte dieses Konstrukt ohne tiefere Hacks funktionieren. Trotzdem bin ich nicht wirklich zufrieden, mir erscheint die Lösung unnötig umständlich und "filigran" ... ich habe nur absolut keine bessere Idee. Wenn Euch also etwas einfällt, immer her damit :)

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Für diejenigen, die es noch interessiert... :D

    So, Thema ist erstmal durch: Ich habe wie angekündigt einen eigenen UINavigationController für die Master-View benutzt, dieser agiert auch als UINavigationBarDelegate und wird gefragt, ob ein Item vom Stack entfernt werden soll. Also quasi genau so, die von @MCDan empfohlen, hier noch einmal ein DICKES Danke!

    Die entsprechende Methode gibt nur dann ein YES zurück, wenn die relevante Datei keine ungesicherten Änderungen aufweist. Andernfalls ruft sie einen Dialog zum Speichern auf. Da dieser auch an anderer Stelle benötigt wird, gibt es dafür eine eigene Methode im DetailViewController. Code-seitig sieht es (nur für den iPhone- / iPhone-Plus-Portrait-Mode nun so aus:

    Quellcode

    1. - (id)initWithCoder:(NSCoder *)aDecoder
    2. {
    3. if (self = [super initWithCoder:aDecoder])
    4. {
    5. self.navigationBar.delegate = self;
    6. }
    7. return self;
    8. }
    9. - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
    10. {
    11. STBAppDelegate *appDelegate = (STBAppDelegate *)[UIApplication sharedApplication].delegate;
    12. STBMasterViewController *masterVC = appDelegate.masterViewController;
    13. STBDetailViewController *detailVC = masterVC.detailViewController;
    14. if (detailVC.designIsDirty)
    15. {
    16. [detailVC presentSaveDialogAndLoadFromURL:nil];
    17. }
    18. else
    19. {
    20. [super popViewControllerAnimated:YES];
    21. }
    22. return !detailVC.designIsDirty;
    23. }
    Alles anzeigen
    Unschön finde ich die Art, auf Master- und Detail-ViewController zuzugreifen, wollte mich aber auch nicht auf die verschiedenen Konstellationen des viewControllers:-Property vom UISplitViewController einlassen.

    Ich war zwischenzeitlich auch schon so weit, den Gedanken des Speicherdialoges gänzlich in die Tonne zu treten und - ähnlich wie Numbers oder Pages - Änderungen direkt auch zu speichern. Persönlich stehe ich mit dieser Philosophie aber immer noch auf Kriegsfuss und befürchte viele "Fehlverhalten" bei meinen Benutzern, die selbigen Dialog aus der aktuellen App-Version kennen. Mal sehen, wann ich umdenke, aus Code-Sicht ist das jetzige Konstrukt recht umständlich...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • In navigationBar:shouldPopItem: brauchst Du eigentlich kein

    Quellcode

    1. [super popViewControllerAnimated:YES]
    aufrufen. Ein

    Quellcode

    1. return YES;
    sollte in diesem Fall reichen, da der Navigation Controller ja ein popViewControllerAnimated: aufruft, wenn navigationBar:shouldPopItem: YES zurück liefert. ;)

    Wenn Du einen Custom UINavigationController verwendest, dann brauchst Du das UINavigationBarDelegate Protokoll eigentlich nicht mehr. Da könntest dann auch einfach die Methode popViewControllerAnimated: überschreiben und dort entscheiden, ob der ViewController gepoppt werden kann oder nicht. In diesem Fall könntest Du sogar den topViewController des NavigationControllers fragen, ob dieser die Methode designIsDirty kennt und diese dann aufrufen und auswerten. Wenn man schon in Objective-C programmiert, dann kann man die Dynamik zur Laufzeit auch nutzen. ;)
  • Also bei mir wurde ohne das [super popViewControllerAnimated:YES] die NavigationBar angepasst, aber der ViewController nicht entsprechend aktualisiert. Und beim Überschreiben der von Dir genannten Methode - mein erster Ansatz - ist es genau umgekehrt: Die NavigationBar ist bereits geändert, wenn die Datei „dirty“ ist und im Stack nicht zurück gegangen werden soll. Daher die „should...“-Delegate-Methode.

    Der UISplitViewController ist schon speziell :D

    Mattes

    Edit: Den erstgenannte Effekt (wenn die „should...“-Methode YES liefert) haben auch andere: Link, ich hatte eigentlich auch das von @MCDan beschriebene Verhalten erwartet.
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MyMattes () aus folgendem Grund: Ergänzung zu Delegate-Methode

  • Kurzes Feedback zum grundsätzlichen Vorgehen - wen es interessiert:

    Ich habe das Benutzer-Konzept geändert und eben ganze Code-Blöcke gelöscht ... unter anderem auch die o. g. Anpassung des UINavigationControllers, die übrigens sehr gut funktioniert hat. Grund für dieses geänderte Vorgehen ist ein sehr aufwändiges File-Handling, um ein wirklich konsistentes Ergebnis zu erhalten: In der UISplitView werden gleichzeitig Dateilisten und -inhalte angezeigt. Wenn andere Dateien ausgewählt werden, erschien der o. g. Dialog ("Speichern", "Verwerfen", "Abbrechen"). Spätestens beim Abbrechen wird es haarig, da dann auch die Selektion der Datei verworfen werden muss. Wenn dazu noch Verzeichnis-Wechsel in der MasterView kommen, wird es richtig eklig.

    Nicht falsch verstehen: Das kann man machen - und ich habe den Großteil meiner Freizeit in den letzten zwei Wochen damit verbracht - aber es fühlt sich einfach falsch an. Ich habe nun beschlossen, Dateiänderungen direkt zu speichern (Undo-Manager ist implementiert) und damit gut. Wer nun erst später merkt, dass er vorgenommene Änderungen eigentlich unter einem anderen Dateinamen speichern wollte, hat Pech gehabt. Genau wie bei Pages, Numbers, Keynote, ... Autosave eben.

    Der Code ist viel cleaner, die Benutzerführung konsistent. Ich bin froh, diesen Schnitt gemacht zu haben, auch wenn mir die Entscheidung nicht leicht fiel.

    Schönen Rest-Sonntag, Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.