1

I am used to performing app initialization in applicationDidFinishLaunching in iOS, but in appKit it is getting called after the main view's draw method! It is too early to draw anything since the app hasn't been initialized. Here is the order:

  1. viewDidLoad (main view controller)
  2. draw(_ dirtyRect:) (view of main controller)
  3. applicationDidFinishLaunching (too late!)

The API reference says the following about applicationDidFinishLaunching

This method is called after the application’s main run loop has been started but before it has processed any events.

Thus a draw event should be posted after applicationDidFinishLaunching. I am not used to this behavior -- what is going on?

wcochran
  • 10,089
  • 6
  • 61
  • 69
  • How does the main view controller come into existence? – matt Apr 16 '17 at 02:58
  • @matt from storyboard – wcochran Apr 16 '17 at 02:59
  • I'm curious about what "I am not used to this behavior" means. Used to, from what context? — Oh, I see! You're coming from iOS. Okay, so Cocoa on the desktop is not the same as Cocoa Touch in iOS. No surprise there. You have a _lot_ of differences to get used to; this is the least of them, I assure you. – matt Apr 16 '17 at 03:14
  • See http://stackoverflow.com/questions/36681587/os-x-storyboard-calls-viewdidload-before-applicationdidfinishlaunching and http://stackoverflow.com/questions/36128229/storyboard-ui-loaded-before-applicationdidfinishlaunching-call-is-made and several others - it isn't as if this has never been noticed before. – matt Apr 16 '17 at 03:26
  • Yeah I read through those,.. didn't see a satisfactory answer... really don't see the use of applicationDidFinishLaunching if I can't initialize the app state with it – wcochran Apr 16 '17 at 04:03
  • I think the way to understand this is to realize that you are looking at very old documentation but using very new technology. `applicationDidFinishLaunching` was around back before there were view controllers and storyboards, and the app delegate typically contained the heart of your application's functionality. Now, however, you have adopted a very new technology, storyboards and view controllers, under which that functionality is split up into separate view controllers, each governing its own view. This changes the timing, meaning, and usage of `applicationDidFinishLaunching`. – matt Apr 20 '17 at 18:09
  • @matt the templates generated from Xcode lead you to assume that `applicationDidFinishLaunching` is meant to be used. I never would have used it except that the template suggested that is now the place to do initialization. I see why "The Bird Nerd Ranch" guide has you delete the templates. – wcochran Apr 21 '17 at 17:56
  • I do use `applicationDidFinishLaunching`. But not for things that need to happen in relation to the drawing of the initial view controller's view! – matt Apr 21 '17 at 19:55

1 Answers1

6

You're just making a false assumption. The initial view controller's viewDidLoad does fire before applicationDidFinishLaunching is called. That's because the runtime loads the storyboard's initial window controller, and causes its view to be loaded, before calling applicationDidFinishLaunching on the app delegate.

If you need an event before the main view's draw, implement applicationWillFinishLaunching. But it would be even better, since you now know the actual order of events, to do your application initialization in the main view controller's viewDidLoad, as it is even earlier. After all, if what you draw initially depends on an initialization you perform earlier, viewDidLoad seems to fit perfectly.

The earliest event you can get in a conventional modern storyboard-based launch is the app delegate's awakeFromNib. But be careful because in macOS it can be called more often than you might expect. (Actually, the class method initialize is even earlier, but be warned that you can't implement that in Swift.)

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • In my Objective-C Cocoa days (strokes beard), I used to do some initializations in the class method `initialize`, or even (to get earlier than that) in `main`! – matt Apr 16 '17 at 03:20
  • But the docs specifically say that applicationDidFinishLaunching is called *before* the first event is posted. Here the draw event is happening before (maybe I misunderstand view events). I am not sure what I would use applicationDidFinishLaunching for... – wcochran Apr 16 '17 at 04:00
  • I will do my initialization in viewDidLoad and move on... thanks for the trouble – wcochran Apr 16 '17 at 04:05
  • 1
    This also makes no sense to me.... what the hell is the point of ```applicationDidFinishLaunching``` if it runs after ```viewDidLoad```?? Seems pretty pointless to be honest. I too will perform my initialisation in the ```viewDidLoad``` method, as everything else that I have tried has failed. – Supertecnoboff Jul 06 '17 at 14:42
  • You can try this: https://stackoverflow.com/a/73659184/6709940 – ImShrey Sep 09 '22 at 08:13