2015-08-11 16 views
9

Sto sviluppando un'applicazione OSX in cui mostro prima una finestra di accesso/registrazione se l'utente non ha ancora effettuato l'accesso.Visualizzazione condizionale di NSViewController all'avvio dell'app

Dopo il login, mostro il mio controller di visualizzazione principale.

Se l'utente è già connesso (un token è memorizzato), l'applicazione deve avviarsi direttamente con il controller di visualizzazione principale.

Sono nuovo nello sviluppo di OSX, ho cercato su Google questo tipo di scenario ma non ho trovato nulla.

Quindi sono andato con quello che penso dovrebbe funzionare. Funziona a volte, a volte ottengo una finestra vuota.

Nello storyboard ho lasciato il menu principale e il controller della finestra. Ho rimosso il seguito "contiene" nel mio controller di visualizzazione principale.

In AppDelegate, ho messo questo:

func applicationDidFinishLaunching(aNotification: NSNotification) { 

    if loggedIn { 
     self.showViewController(NSStoryboard.mainViewController()) 

    } else { 
     let loginController = NSStoryboard.loginViewController() 
     loginController.delegate = self 
     self.showViewController(loginController) 
    } 
} 

private func showViewController(viewController: NSViewController) { 
    if let mainWindow = NSApplication.sharedApplication().mainWindow { 
     mainWindow.contentViewController = viewController 

    } else { 
     print("Error: No main window!") 
    } 
} 

Circa la metà dei tempi della finestra è vuoto e vedo nella console "Errore: No finestra principale". Ho pensato che forse posso usare applicationDidBecomeActive ma questo si chiama fondamentalmente quando si tratta di primo piano e questo non è quello che mi serve.

Inoltre, i tempi in cui funziona, e io il log-in, poi voglio mostrare la visualizzazione principale regolatore:

func onLoginSuccess() { 
    self.showViewController(NSStoryboard.mainViewController()) 
} 

E qui ho anche ottenere "Errore: nessuna finestra principale!" (sempre) e non succede nulla.

La documentazione dicono segue circa mainWindow essere nullo:

The value in this property is nil when the app’s storyboard or nib file has not yet finished loading. It might also be nil when the app is inactive or hidden.

Ma perché è lo storyboard non terminato il caricamento o l'applicazione inattiva quando Sto lanciando esso? E al momento del login l'app è sicuramente attiva e in primo piano e la finestra principale è sempre nullo.

Cosa sto sbagliando? Come posso implementare questo flusso di lavoro? In alternativa, potrei creare un controller di visualizzazione "genitore", avere quello connesso alla finestra nello storyboard e aggiungere il login o il controller di visualizzazione principale come controller di visualizzazione nidificati a quello. Ma non mi piace davvero dover aggiungere un controller di visualizzazione nulla.

sto utilizzando XCode 7 (beta 4), Swift 2, OSX 10.10.4

Edit:

I metodi NSStoryboard provengono da un interno, sembra che questo:

extension NSStoryboard { 

    private class func mainStoryboard() -> NSStoryboard { return NSStoryboard(name: "Main", bundle: NSBundle.mainBundle()) } 
    private class func signupStoryboard() -> NSStoryboard { return NSStoryboard(name: "LoginRegister", bundle: NSBundle.mainBundle()) } 

    class func mainViewController() -> ViewController { 
     return self.mainStoryboard().instantiateControllerWithIdentifier("MainViewController") as! ViewController 
    } 

    class func loginViewController() -> LoginViewController { 
     return self.signupStoryboard().instantiateControllerWithIdentifier("LoginViewController") as! LoginViewController 
    } 

    class func registerViewController() -> RegisterViewController { 
     return self.signupStoryboard().instantiateControllerWithIdentifier("RegisterViewController") as! RegisterViewController 
    } 
} 
+0

'NSStoryBoard.mainViewController()' - da dove viene questo metodo di classe? In generale OSX ha un po 'di magia in NSApplicationMain che tenta di inizializzare un pennino principale (storyboard?) Da info.plist. E sto cercando di rintracciarlo con gli storyboard ma sono bloccato su dove i metodi mainViewController e loginViewController provengono da ... – stevesliva

+2

Se si sta utilizzando un oggetto NSWindowController separato, perché non fare semplicemente riferimento a quella finestra direttamente? –

+0

@stevesliva è in un'estensione, l'ho aggiunto alla domanda – Ixx

risposta

2

Per inserire la soluzione che abbiamo trovato nei commenti come risposta:

Apparentemente NSApplication.sharedApplication().mainWindow è una finestra diversa dalla mia finestra principale nello storyboard.

Così, ho creato una sottoclasse NSWindowController e l'ho assegnata alla finestra nello storyboard, usando il controllo identità.

Quindi ho spostato la logica che avevo in app delegato a questo NSWindowController.Assomiglia a questo:

class MainWindowController: NSWindowController, LoginDelegate { 

    override func windowDidLoad() { 

     if loggedIn { 
      self.onLoggedIn() 
     } else { 
      let loginController = NSStoryboard.loginViewController() 
      loginController.delegate = self 
      self.contentViewController = loginController 
     } 
    } 

    func onLoggedIn() { 
     self.contentViewController = NSStoryboard.mainViewController() 
    } 

    func onLoginSuccess() { 
     self.onLoggedIn() 
    } 
} 

* Grazie Lucas Derraugh per avermi indicato nella giusta direzione!

Problemi correlati