Exibindo condicionalmente o NSViewController no lançamento do aplicativo

9

Estou desenvolvendo um aplicativo OSX no qual mostro primeiro uma janela de login / registro se o usuário ainda não tiver efetuado login.

Após o sucesso do login, mostro meu controlador de visualização principal.

Se o usuário já estiver conectado (um token é armazenado), o aplicativo precisará ser iniciado diretamente com o controlador de exibição principal.

Sou novo no desenvolvimento do OSX, pesquisei por esse tipo de cenário, mas não consegui encontrar nada.

Então eu comecei com o que eu acho que deveria funcionar. Funciona às vezes, às vezes eu recebo uma janela em branco.

No storyboard, deixo o menu principal e o controlador de janela. Eu removi o "contém" segue para o meu controlador de visualização principal.

No AppDelegate, eu coloquei isto:

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!")
    }
}

Cerca de metade das vezes a janela está vazia e vejo no console "Erro: Nenhuma janela principal!". Eu pensei que talvez eu possa usar applicationDidBecomeActive , mas isso é chamado basicamente quando se trata de primeiro plano e não é isso que eu preciso.

Além disso, nos horários em que ele funciona e eu faço login, quero mostrar o controlador da visualização principal:

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

E aqui eu também recebo "Erro: Nenhuma janela principal!" (sempre) e nada acontece.

Os documentos dizem que seguir sobre mainWindow é nulo:

  

O valor nesta propriedade é nulo quando o storyboard do aplicativo ou o arquivo de ponta ainda não terminou de ser carregado. Também pode ser nulo quando o aplicativo está inativo ou oculto.

Mas por que o storyboard não terminou o carregamento ou o aplicativo está inativo quando eu o inicio? E no sucesso do login, o aplicativo está definitivamente ativo e em primeiro plano, e a janela principal é sempre nula.

O que estou fazendo de errado? Como posso implementar esse fluxo de trabalho? Alternativamente, eu poderia criar um controlador de visão "pai", ter aquele conectado à janela no storyboard e adicionar o controlador de login ou de visualização principal como controladores de visualização aninhados a ele. Mas não gosto de ter que adicionar um controlador de visualização do tipo nada.

Estou usando o XCode 7 (beta 4), Swift 2, OSX 10.10.4

Editar:

Os métodos do NSStoryboard vêm de uma extensão, assim:

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
    }
}
    
por Ixx 11.08.2015 в 21:33
fonte

1 resposta

3

Para colocar a solução, encontramos nos comentários como resposta:

Aparentemente, NSApplication.sharedApplication().mainWindow é uma janela diferente da minha janela principal no storyboard.

Então, criei uma subclasse NSWindowController e a atribui à janela no storyboard, usando o inspetor de identidade.

Então mudei a lógica que eu tinha no delegado do aplicativo para este NSWindowController. Parece assim:

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()
    }
}

* Obrigado Lucas Derraugh por me apontar na direção certa!

    
por Ixx 12.08.2015 / 13:29
fonte