在应用启动时有条件地展示NSViewController

时间:2015-08-11 19:33:40

标签: macos swift swift2

我正在开发一个OSX应用程序,如果用户尚未登录,我首先会显示一个登录/注册窗口。

登录成功后,我会显示我的主视图控制器。

如果用户已登录(存储了令牌),则应用必须直接使用主视图控制器启动。

我是OSX开发的新手,我搜索了这种情况,但找不到任何东西。

所以我想起了我认为应该工作的东西。它有时会起作用,有时我会得到一个空白的窗口。

在故事板中,我让主菜单和窗口控制器。我删除了“包含”segue到我的主视图控制器。

在AppDelegate中,我把它放在:

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

大约有一半时间窗口是空的,我在控制台中看到“错误:没有主窗口!”。我想也许我可以使用applicationDidBecomeActive但这基本上被称为前景,这不是我需要的。

此外,它工作的时间,我登录,然后我想显示主视图控制器:

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

在这里我也得到了“错误:没有主窗口!” (总是)没有任何反应。

文档说关于mainWindow为零:

  

当app的storyboard或nib文件尚未完成加载时,此属性中的值为nil。当应用程序处于非活动状态或隐藏状态时,它也可能是零。

但是为什么故事板未完成加载或应用程序在我启动时处于非活动状态?在登录成功时,应用程序肯定处于活动状态并位于前台,主窗口始终为零。

我做错了什么?我该如何实现这个工作流程?或者,我可以创建一个“父”视图控制器,将其连接到故事板中的窗口,并将登录或主视图控制器添加为嵌套视图控制器。但是不要真的喜欢添加一个什么都不做的视图控制器。

我正在使用XCode 7(beta 4),Swift 2,OSX 10.10.4

编辑:

NSStoryboard方法来自扩展,它看起来像这样:

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

1 个答案:

答案 0 :(得分:3)

将我们在评论中找到的解决方案作为答案:

显然NSApplication.sharedApplication().mainWindow与故事板中的主窗口不同。

因此,我创建了一个NSWindowController子类,并使用身份检查器将其分配到故事板中的窗口。

然后我将app delegate中的逻辑移到了这个NSWindowController。它看起来像这样:

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

*感谢Lucas Derraugh指出我正确的方向!