58

I recently had a problem in my app where some of the subviews I was creating in a UIViewController subclass's -awakeFromNib method were disappearing from the view. After some poking around I found that moving the code I had put in -awakeFromNib to -viewDidLoad solved the problem. Seems that -awakeFromNib gets called only once when the UIViewController is unarchived from the nib, and -viewDidLoad gets called every time the view is unarchived.

So what's the best practice? It looks like UIViewController's -awakeFromNib shouldn't be adding any views to the view, that kind of stuff should be done in -viewDidLoad. Am I understanding this correctly? Or am I more confused than I thought?

Chris Hanson
  • 54,380
  • 8
  • 73
  • 102
Mike Akers
  • 12,039
  • 14
  • 58
  • 71
  • 6
    remember, viewDidLoad only applies to VIEW CONTROLLERS, not views as such. awakeFromNib actually applies to "everything" since it is part of NSObject. and remember, if dealing with a view do NOT run, say, animations in awakeFromNib because the view is still very likely being animated in to position, etc. – Fattie Dec 04 '13 at 09:08

5 Answers5

67

awakeFromNib is called when the controller itself is unarchived from a nib. viewDidLoad is called when the view is created/unarchived. This distinction is especially important when the controller's view is stored in a separate nib file.

mfaani
  • 33,269
  • 19
  • 164
  • 293
Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • 8
    iOS devs beware [behaviour on iOS is different](http://stackoverflow.com/a/2196262/618653) – t0rst Jul 28 '12 at 11:59
  • In the spec of `awakeFromNib`, "it is guaranteed to have all its outlet and action connections already established", so which outlet is it? Is it the view outlet? – onmyway133 Dec 17 '15 at 03:50
  • 1
    what's the difference between created & unarchived? does unarchived refer to files made in a non-programmatical ie (storyboard and xib) way? and created refer to pure programmatic? – mfaani Aug 01 '16 at 18:25
  • 1
    Unarchived means the view came from a storyboard/xib. Created means it was instantiated programmatically. – Lily Ballard Aug 03 '16 at 00:49
24

Also important is that the awakeFromNib function will never be called after recovering from memory warning. But, the viewDidLoad function will be called.

arunjos007
  • 4,105
  • 1
  • 28
  • 43
Krešimir Prcela
  • 4,257
  • 33
  • 46
12

Yes, it's correct. You shouldn't really rely on awakeFromNib to do that kind of tasks.

awakeFromNib is similar to an event that's called after deserialization in .NET. viewDidLoad is similar to Load event in .NET.

If you are familiar with the concepts from .NET, this should be enough, I think.

Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
7

I'll try to answer by giving an example:

If define customCell class and customCell.xib file, and then load the cell by using
- (NSArray *)loadNibNamed:(NSString *)name owner:(id)owner options:(NSDictionary *)options, awakeFromNib gets called when the objects in the xib are unarchived.

If you define a customViewController, then when the customViewController is created using - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil. viewDidLoad will get called when it's loaded into view hierarchy.

Some related confusing methods:

  • (void)loadView; This is where subclasses should create their custom view hierarchy if they aren't using a nib. If you don't specify a nib name, then loadView will attempt to load a nib whose name is the same as your view controller's class. If no such nib exists, then you must either call -setView: before -view is invoked, or override the -loadView method to set up your views programatically. -loadView should never be called directly.

  • (void)viewDidLoad: Called after the view has been loaded. For viewControllers created in code, this is after -loadView. For view controllers unarchived from a nib, this is after the view is set.

mfaani
  • 33,269
  • 19
  • 164
  • 293
hrchen
  • 1,223
  • 13
  • 17
-1

For a ViewController, IBOutlets are available in viewDidLoad()

Here stackView represents an IBOutlet in a ViewController, stackView is nil in awakeFromNib, but it has been instantiated when viewDidLoad() is called.

IBOutlets state in awakeFromNib() vs IBOutlet state in viewDidLoad()

andreskwan
  • 1,152
  • 1
  • 13
  • 13
  • 3
    you are missing a super.awakeFromNib and super.viewDidLoad calls. Once super.awakeFromNib is called then all IBOutlets of type Object will be initiated except the view and IBOutlets which are aliases to the view subviews. – Blazej SLEBODA Jul 30 '20 at 09:17