Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
723 views
in Technique[技术] by (71.8m points)

xcode - OS X storyboard calls viewDidLoad before applicationDidFinishLaunching

I created a Mac OS X application in Xcode using storyboards. For some reason the applicationDidFinishLaunching method in the AppDelegate is being called after viewDidLoad in the NSViewControllers. As with iOS apps, I thought viewDidLoad is supposed to be called before applicationDidFinishLaunching? Do storyboards in OS X apps initialize the view controllers before the app has finished launching?

I am using the applicationDidFinishLaunching method to register default settings into NSUserDefaults. Unfortunately, registering the default values is happening after the views in the storyboard are loaded. Therefore, when I set up the view in each view controller using viewDidLoad, the defaults data in NSUserDefaults has not been set. If I can't use applicationDidFinishLaunching to register NSUserDefaults in OS X storyboard apps, then how I set the defaults before viewDidLoad is called?

To fix this issue, in the Main.storyboard in Xcode, I turned off "Is Initial Controller" for the main window. I assigned a storyboard ID to the main window as "MainWindow". Then in the AppDelegate I entered the following code:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationDidFinishLaunching(aNotification: NSNotification) {

        let storyboard = NSStoryboard(name: "Main", bundle: nil)
        let mainWindow = storyboard.instantiateControllerWithIdentifier("MainWindow") as! NSWindowController
        mainWindow.showWindow(nil)
        mainWindow.window?.makeKeyAndOrderFront(nil)

    }
}

The app does not crash but now the window never appears. The following image displays the storyboard I'm working with:

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Correct, the lifecycle is a wee bit different in OS X.

Instead of letting the storyboard be your initial interface (this is defined in the General settings of your project), you can instead set up a MainMenu xib file and designate that as your main interface, then in your applicationDidFinishLaunching method in your AppDelegate you can programmatically instantiate your storyboard after you have completed your other initialization code.

I recommend checking out Cocoa Programming for OS X: The Big Nerd Ranch Guide if you haven't already; one nice thing they do in their book is actually have you get rid of some of the default Xcode template stuff and instead they have you set up your initial view controller the "right" way by doing it explicitly.

You might put something like this in your applicationDidFinishLaunching:

NSStoryboard *mainStoryboard = [NSStoryboard storyboardWithName:@"Main" bundle:nil];
MyWindowController *initialController = (MyWindowController *)[mainStoryboard instantiateControllerWithIdentifier:@"myWindowController"];
[initialController showWindow:self];
[initialController.window makeKeyAndOrderFront:self];

This assumes that you've already changed "Main Interface" to something like MainMenu.xib.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...