WindowController öffnet Fenster immer wieder

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

  • WindowController öffnet Fenster immer wieder

    [macOS, Objective-C, Storyboards]

    Hallo zusammen,
    habe das Problem, dass der Window Controller mehrfach das Fenster öffnet.
    Konkret: Durch den untenstehenden Code, wird das Info-Fenster über die App geöffnet. Wurde das Info-Fenster aber bereits geöffnet und ist noch irgendwo im Hintergrund oder minimiert, wird das Info-Fenster erneut aus dem Controller erzeugt, anstatt das bereits geöffnete (minimierte) Fenster in den Vordergrund zu setzen. So kann es sein, dass das selbe Fenster 5 mal geöffnet ist und es doch nur einmal benötigt wird.

    Quellcode

    1. -(IBAction)ShowAboutPanel:(id)sender
    2. {
    3. NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:@"AboutPanel" bundle:nil];
    4. _AboutPanelWindowController = [storyBoard instantiateInitialController];
    5. [_AboutPanelWindowController showWindow:self];
    6. NSLog(@"Show About Panel");
    7. }
    Gibt es hier einen Trick? :whistling:

    LG Scotch
  • Das beschriebene Verhalten entspricht eigentlich dem o.a. Source Code.

    Bevor Du per

    C-Quellcode

    1. _AboutPanelWindowController = [storyBoard instantiateInitialController];
    immer einen neuen WindowController erzeugst, solltest Du evtl. prüfen, ob schon ein WindowController für das AboutPanel erzeugt wurde.

    Dies könnte dann so aussehen

    C-Quellcode

    1. -(IBAction)ShowAboutPanel:(id)sender
    2. {
    3. // Gibt es schon einen WindowController für das About Fenster?
    4. if (_AboutPanelWindowController == nil)
    5. {
    6. // Nein -> WindowController erzeugen
    7. NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:@"AboutPanel" bundle:nil];
    8. _AboutPanelWindowController = [storyBoard instantiateInitialController];
    9. }
    10. // Window anzeigen
    11. [_AboutPanelWindowController showWindow:self];
    12. NSLog(@"Show About Panel");
    13. }
    Alles anzeigen

    Allerdings bleibt damit der WindowController immer im Speicher, auch wenn das About Fenster bereits geschlossen wurde.

    Es wäre daher optimal, wenn Du auf das Schließen des About Fensters reagieren und den WindowController dann frei geben würdest. Dafür bietet ein NSWindow die NSWindowWillCloseNotification an.

    Dies würde dann so aussehen:

    C-Quellcode

    1. -(IBAction)ShowAboutPanel:(id)sender
    2. {
    3. // Gibt es schon einen WindowController für das About Fenster?
    4. if (_AboutPanelWindowController == nil)
    5. {
    6. // Nein -> WindowController erzeugen
    7. NSStoryboard *storyBoard = [NSStoryboard storyboardWithName:@"AboutPanel" bundle:nil];
    8. _AboutPanelWindowController = [storyBoard instantiateInitialController];
    9. // Einen Notification Observer hinzufügen, der auf das Schließen des Fensters reagiert
    10. __block id <NSObject> aboutWindowCloseObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:_AboutPanelWindowController.window queue:nil usingBlock:^(NSNotification * _Nonnull note) {
    11. // Das Fenster wurde geschlossen, also den Notification Observer entfernen.
    12. [[NSNotificationCenter defaultCenter] removeObserver:aboutWindowCloseObserver];
    13. // und den Observer,
    14. aboutWindowCloseObserver = nil;
    15. // sowie den WindowController freigeben
    16. _AboutPanelWindowController = nil;
    17. }];
    18. }
    19. // Window anzeigen
    20. [_AboutPanelWindowController showWindow:self];
    21. NSLog(@"Show About Panel");
    22. }
    Alles anzeigen
  • Hallo zusammen,

    das gleiche Problem habe ich jetzt auch in Swift. Das viele Probieren und recherchieren hat nicht zum Erfolg geführt.
    So prüfe ich (zwecklos), ob der Window Controller das Window bereits geöffnet habe.


    Quellcode

    1. @IBAction func OpenDemoWindow(_ sender : Any) {
    2. let storyboard = NSStoryboard(name: NSStoryboard.Name(rawValue: "About"), bundle: nil)
    3. let windowController = storyboard.instantiateInitialController() as! NSWindowController
    4. if (!windowController.isWindowLoaded) {
    5. windowController.showWindow(self)
    6. }
    7. else {
    8. // Fenster bereits geladen, nach vorne bringen
    9. }
    10. }
    Alles anzeigen
    Was mache ich falsch? ?(
  • Du verwendest nur lokale Variablen in OpenDemoWindow.
    windowController wird daher bei jedem Aufruf neu erstellt und das Fenster wurde
    noch nicht angezeigt.

    Wenn du auf Klassenebene windowController als NSWindowController? (Optional!) deklarierst,
    kannst du zu Beginn der Methode prüfen, ob windowController nil ist. Falls ja, muss er erst
    erstellt werden. Falls nein, kann direkt isWindowLoaded abgefragt werden.
  • Die Sache hat nur einen Haken:

    Die App läuft sowohl als normale window app und kann aber auch nur als status bar app aktiv sein.

    Rufe ich die Fenster-Öffnen-Funktion im normalen window modus auf, wird das neue Fenster korrekt (ordered front) angezeigt.
    Läuft die app als status bar app:

    Quellcode

    1. NSApp.setActivationPolicy(.prohibited)

    , so wird das Fenster zwar geöffnet, schlummert aber im Hintergrund hinter den anderen aktiven Fenstern.

    Folgendes habe ich probiert, um das Fenster in den Vordergrund zu rücken:

    Quellcode

    1. NSApp.activate(ignoringOtherApps: true)
    2. view.window?.makeKeyAndOrderFront(self)
    3. view.window?.center()
    4. view.window?.orderFrontRegardless()
    Habe ich einen falschen Ansatz?