Search code examples
macoscocoaswift4viewcontrollerxcode10

How to set initial controller programmatically from storyboard in Cocoa using Swift 4 Xcode 10?


Introduction:

I want to create an app that displays some "user guide" on its first launch, I've already finished the part that detects if the app is first launch, but when it comes to the setting view controller part, I can't figure out how to do it.

Current Situation:

I've done a lot of researches and seen a lot of Q/A articles on topics like "How to set initial view controller programmatically in swift", but basically all of them are using ios development as an example, which none of their UIWindow or UINavigationController(rootViewController:) matches in the OSX development. And then I found out it seems that there is no such thing as didFinishLaunchingWithOptions in the AppDelegate.swift file, instead, there's only an applicationDidFinishLaunching(_ aNotification: Notification).

Question:

I already unchecked the Is Initial Controller option for both of my View Controllers, and both of them has Storyboard ID (identifier?) and their own specified class.

MainPageController

UserGuidePageController

Or should I specify and identify my Window Controllers too? Cuz' I have no idea about what to do with the Window Controllers..

What do I need to do in order to set the initial view controller for my application in AppDelegate?

P.S. Here is the picture of my interface view:

Storyboard interface

AppDelegate.swift

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

  let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
  var window = MainWindow().window

  func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) - > Bool {
    return true
  }

  func applicationDidFinishLaunching(_ aNotification: Notification) {
    // Insert code here to initialize your application
    let firstLaunch = UserDefaults.isFirstLaunch()
    let mainPageController = storyboard.instantiateController(withIdentifier: NSStoryboard.Name("MainPageController")) as? MainPageController
    let userGuidePageController = storyboard.instantiateController(withIdentifier: NSStoryboard.Name("MainPageController")) as? UserGuidePageController
    if !firstLaunch {
      print("first run")
      window?.contentViewController = userGuidePageController
    } else {
      print("not first run")
      window?.contentViewController = mainPageController
    }
  }

  func applicationWillTerminate(_ aNotification: Notification) {
    // Insert code here to tear down your application
  }
}

I tried this way, but it didn't work out pretty well, is there anything wrong with my code?


Solution

  • at the beginning you need to handle such scenario from the app delegate class for iOS APPs

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    
    
    let shouldShowUserGuide = // your cached key from user defaults for example
    
    let mainController = //MainPageController Instance
    let userGuide = //UserGuidePageController Instance
    
    
    if shouldShowUserGuide {
    window.rootViewController = userGuide 
    }else{
    window.rootViewController = mainController
    }
    window.makeKeyAndVisisble()
      return true
    }
    

    // this code I just write it on sublime not from xcode so may be you need to format it and fix any syntax problems

    For OSX MainWindow: NSWindowController

    func applicationDidFinishLaunching(_ aNotification: Notification) {
            let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: Bundle.main)
            var window = storyboard.instantiateController(withIdentifier: "MainWindow") as! NSWindowController
            let firstLaunch = true//UserDefaults.isFirstLaunch()
            let mainPageController = storyboard.instantiateController(withIdentifier: "MainController") as! NSViewController
            let userGuidePageController = storyboard.instantiateController(withIdentifier: "UserGuideController") as! NSViewController
            if firstLaunch {
                print("first run")
                window.contentViewController = userGuidePageController
            } else {
                print("not first run")
                window.contentViewController = mainPageController
            }
            window.showWindow(self) // needed as long as your window controller has no static window content (No Content View Controller)
        }