39

On the iPhone I use UIViewController's viewDidLoad to run code to set up the view.

How can I do that with NSViewController?

I've tried loadView but it doesn't work...

pkamb
  • 33,281
  • 23
  • 160
  • 191
TesX
  • 931
  • 1
  • 9
  • 29

6 Answers6

49

I figured it out within minutes of posting my comment. Adding my finding as an answer because it is an example which is missing in the docs. The below code will give you the viewDidLoad method that you want. Its so easy in a way that i wonder why Apple has not implemented it yet in OS X.

- (void)viewWillLoad {
    if([NSViewController instancesRespondToSelector:@selector(viewWillLoad)]) {
        [super viewWillLoad];
    }

    ...
}

- (void)viewDidLoad {
    if([NSViewController instancesRespondToSelector:@selector(viewWillLoad)]) {
        [super viewDidLoad];
    }
}

- (void)loadView {
    BOOL ownImp = ![NSViewController instancesRespondToSelector:@selector(viewWillLoad)];

    if(ownImp) {
        [self viewWillLoad];
    }

    [super loadView];

    if(ownImp) {
        [self viewDidLoad];
    }
}

Original source: http://www.cocoabuilder.com/archive/cocoa/195802-garbage-collection-leaks-and-drains.html

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
Chintan Patel
  • 3,175
  • 3
  • 30
  • 36
  • 7
    One possible danger with this is that Apple could add `-viewWillLoad` and `-viewDidLoad` methods to `NSViewController` one day. If so, your override of those methods would be called twice. – Mike Abdullah Mar 03 '11 at 12:47
  • Thank you so much for this solution! I had been searching for weeks for this. – James Testa Mar 03 '11 at 12:55
  • 1
    @Mike... Your concern is valid and now with 10.7 Lion being more like iOS, i think it may just make it in Lion itself. I will be keeping a watch on it so no worries for me but yes, having the same function names can cause trouble otherwise. – Chintan Patel Mar 03 '11 at 18:02
  • 1
    While this is a great example of how to replicate the viewDidLoad functionality on OS X, I'm more concerned with finding the "proper" way of doing this when doing Cocoa desktop development. What is the correct procedure for doing things that you would normally do in viewDidLoad on iOS (like setting up your views after they're loaded from the nib) when developing for OS X? – Christian A. Strømmen Dec 05 '12 at 12:54
  • This is the most "proper" way i could get to in replicating iOS's viewDidLoad on Mac. I have moved back to iOS development since then. – Chintan Patel Dec 06 '12 at 16:13
  • The danger pointed out in the comment above re: Apple introducing ```-viewWillLoad```, ```-viewDidLoad``` (http://stackoverflow.com/questions/3422839/viewdidload-in-nsviewcontroller/24098857#comment5820794_5090825) has now come true: as of 10.10, these methods exist in NSViewController. – mz2 Jun 07 '14 at 15:44
  • Edited in some code to support OS X Yosemite. If the system implements `viewWillLoad`/`viewDidLoad`, use the system implementation, otherwise - use the user's. – Léo Natan Aug 22 '14 at 10:54
  • Hello , Thank you very much for this great code share, however I want to add 1 note : When you will call viewDidLoad it won't go through the NSRunLoop which means the view will not have Bounds because it is not really loaded yet... I think you should go through the run loop -> I want to figure the best way for this, maybe you can help ? – Coldsteel48 May 22 '15 at 22:14
  • [super viewDidLoad]; this line give error in my case base sdk and deployment target = 10.9 in my case. – Sangram Shivankar Apr 06 '18 at 13:45
42

As of OS X 10.10, viewDidLoad is available and supported on NSViewController.

Prior to that, you had to go by this nugget in Snow Leopards' release notes:

Advice for People who Are Looking for -viewWillLoad and -viewDidLoad Methods in NSViewController

Even though NSWindowController has -windowWillLoad and -windowDidLoad methods for you to override the NSViewController class introduced in Mac OS 10.5 does not have corresponding -viewWillLoad and -viewDidLoad methods. You can override -[NSViewController loadView] to customize what happens immediately before or immediately after nib loading done by a view controller.

Tamas Czinege
  • 118,853
  • 40
  • 150
  • 176
Mike Abdullah
  • 14,933
  • 2
  • 50
  • 75
  • I have asked it on http://stackoverflow.com/questions/4492485/when-programming-for-mac-os-x-is-there-an-equivalent-to-viewdidload but might as well ask you too: I read this in the docs and tried to play around with loadView but still i am not able to understand how it helps in doing something "immediately after nib loading". I have an NSTabView in the xib file which is connected properly but still it is always 0x0 when i keep a breakpoint in loadView. – Chintan Patel Feb 23 '11 at 11:06
  • 3
    -1; Obsolete! The linked article no-longer discusses this. :( – Arafangion Sep 01 '11 at 04:17
  • 1
    I think *[viewController loadView]* is not a capable method for replacing viewDidLoad. Because this method will be called by the system every time *[viewController view]* is called. So this method can be called multiple times in once application have running – Alfian Busyro Sep 27 '12 at 09:10
  • @arufian you would be wrong. `-loadView` only gets called when `-view` actually needs to load the view. If it's already been loaded, it does not call through to `-loadView` – Mike Abdullah Sep 27 '12 at 12:46
  • @MikeAbdullah thanks... hmm, actually I did experiments about using `-view`, and after I debugged the program because it took too long load times, I found that `-loadView` is being called again and again and again ... :( – Alfian Busyro Sep 28 '12 at 05:50
  • 2
    @arufian maybe you forgot to hook up the `view` outlet? – Mike Abdullah Oct 08 '12 at 14:58
  • see: http://stackoverflow.com/questions/30174952/backward-compatibility-of-xcode-osx/30196972#30196972 – geowar Oct 14 '15 at 14:35
9

As of OSX 10.10 (Yosemite), there is now a -viewDidLoad, -viewWillAppear, -viewDidAppear, -viewWillDisappear in NSViewController. See WWDC 2014 - Storyboards and Controllers on OS X session for more info, to find out when each of them gets called, etc.

Here's the relevant bit from the 10.10 header docs about -viewDidLoad:

Called after the view has been loaded. For view controllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set. Default does nothing.

- (void)viewDidLoad NS_AVAILABLE_MAC(10_10);
Vaibhav B.
  • 11
  • 3
mz2
  • 4,672
  • 1
  • 27
  • 47
  • I can confirm this.. as of Xcode6-B4 the Apple-provided boilerplate for an `NSVewController` subclass includes `- (void)viewDidLoad { [super viewDidLoad]; // Do view setup here. }`! – Alex Gray Jul 25 '14 at 18:35
5

why don't you try this:

- (void)awakeFromNib {
    //setup code
    NSLog(@"hello there");
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Jesus
  • 8,456
  • 4
  • 28
  • 40
  • 1
    I tend to avoid doing things in `awakeFromNib`, as it can sometimes be called more than once. For example calling `makeViewWithIdentifier:owner:` and passing self as the owner will cause `awakeFromNib` to be called. See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TableView/PopulatingView-TablesProgrammatically/PopulatingView-TablesProgrammatically.html. – Kyle Aug 18 '14 at 12:48
  • kyle i face same problem, awakeFromNib called multiple time due to makeViewWithIdentifier:owner – Sangram Shivankar Apr 24 '17 at 14:07
1

It looks like in 10.10, viewDidLoad is now in NSViewController.

ninjaneer
  • 6,951
  • 8
  • 60
  • 104
-5

hmm actually I would also do this...

- (void)viewWillLoad {

    if (! bool_viewwillload) {

        // execute the code
        bool_viewwillload = true;
    }
}

- (void)viewDidLoad {
    if (! bool_viewdidload) {

        // execute the code
        bool_viewdidload = true;
    }
}

and then just make the load view like this

- (void)loadView {

    [self viewWillLoad];

    [super loadView];

    [self viewDidLoad];
}
Chintan Patel
  • 3,175
  • 3
  • 30
  • 36
johnrubythecat
  • 1,003
  • 1
  • 13
  • 31