30

What is the viewDidLoad for UIView?

I have a UIView with xib. I would like to hide one of it's subviews when it is loaded. I tried to use this.

- (id)initWithCoder:(NSCoder *)aDecoder{
    ....
    _theView.hidden = YES;
}

But the subview _theView is nil at this point.

This answer didn't help me, becouse at moment of creating the UIViewController, the UIView is not created yet. It is created programaticly, later on.

Community
  • 1
  • 1
Luda
  • 7,282
  • 12
  • 79
  • 139

6 Answers6

27

Try

-awakeFromNib method

Or in xib set the view property hidden for your subview

Lithu T.V
  • 19,955
  • 12
  • 56
  • 101
  • @Luda I think this answer is still enough for your question.Why a bounty now..seems closed pretty earlier ? – Lithu T.V Feb 19 '15 at 12:01
25

AwakeFromNib is called only if the view loaded from nib file. layoutSubviews is called for all views, you can add bool _loaded = yes; in the layoutSubviews function and know if the view loaded.

Rebecca
  • 653
  • 6
  • 14
  • 3
    remember to call super on all those methods :D – wolffan Feb 18 '15 at 12:20
  • awakeFromNib will always be called and there's really no need to use `layoutSubviews` here. – Segev Feb 18 '15 at 19:19
  • 3
    @Segev, So if awakeFromNib if called when nib or storyboard is used, it woun't be called if view was created programatically? Only .h and .m or .swift. If so, then your answer is wrong and awakeFromNib is not always called. – Luda Feb 19 '15 at 08:59
6

The accepted answer is misleading. awakeFromNib will always be called, not just if a nib is used. From the apple docs:

awakeFromNib:

Prepares the receiver for service after it has been loaded from an Interface Builder archive, or nib file.

Link

In the next example I've used only a storyBoard You can test this very easily.

This is our ViewController:

enter image description here

ViewController.m:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"viewDidLoad");
}

-(void)awakeFromNib
{
    NSLog(@"awakeFromNib in view controller");
}

@end

RedView.m:

#import "RedView.h"

@implementation RedView

-(void)awakeFromNib
{
        NSLog(@"awakeFromNib inside RedView");
        self.green.hidden = YES;
}

@end

Order of print:

  1. awakeFromNib in view controller
  2. awakeFromNib inside RedView
  3. viewDidLoad

And of course the green view will be hidden.


Edit:

awakeFromNib won't be called if you use only code to create your view but you can call it yourself or better yet, create your own method.

Example without a StoryBoard (only code):

RedView.m:

#import "RedView.h"

@implementation RedView

-(void)loadRedView
{
    NSLog(@"loadRedView");
    self.green = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
    self.green.backgroundColor = [UIColor greenColor];
    [self addSubview:self.green];
    self.green.hidden = YES;
}
@end

ViewController.m:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.red = [[RedView alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
    self.red.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.red];
    [self.red loadRedView];
}

@end
Segev
  • 19,035
  • 12
  • 80
  • 152
  • 1
    So if awakeFromNib if called when nib or storyboard is used, it woun't be called if view was created programatically? Only .h and .m or .swift. If so, then your answer is wrong and awakeFromNib is not always called. – Luda Feb 19 '15 at 08:57
  • Like the apple docs suggest, `Prepares the receiver for service after it has been loaded from an Interface Builder archive, or nib file.` so it wouldn't be called but, you can simply call it your self! I've edited the answer. – Segev Feb 19 '15 at 09:10
  • But that is a hack. You suggesting to call function related to nib, when the is no nib involved – Luda Feb 19 '15 at 10:45
  • Again, the function is **not** related to nib. It works just the same using the StoryBoard. There's nothing hackish about it. You just call a method `UIView` knows. You can create a different method inside the view and call it upon load for example `-(void)fooIsLoading` – Segev Feb 19 '15 at 10:48
  • Yes, it is hackish. A Storyboard is just a different form of nib/xib, so awakeFromNib is also called when the object is loaded from a Storyboard. If you have the option to call awakeFromNib yourself you could just as well call your on `prepareForWhatever` method instead which makes the code clearer. `awakeFromNib` is much older than Storyboards, even older than iOS, that's why it has that possibly misleading name although mostly Storyboards are used nowadays. But the documentation is clear, a Storyboard is an Interface Builder archive. – Joachim Kurz Feb 19 '15 at 12:43
  • I wouldn't consider it that hackish but I agree that calling your own method would be clearer just like i suggested in the previous comment, `-(void)fooIsLoading`. Answer was edited. – Segev Feb 19 '15 at 12:49
2

There is no such method in general. The question is, where is your _theView coming from.

If your view, including its subview, is loaded from the same nib/xib/storyboard then you can use awakeFromNib which will be called after the complete object hierarchy has been loaded from the archive, so your _theView should be set as well.

If your view is created programmatically but does not create the subview for _theView itself, that means there has to be a place in your code where you add that subview. In that case you have two options

  • Either hide _theView from the caller after you added it
  • Or declare a prepareForDisplay method (or similar) on your view class and call that after your view has been created and _theView has been assigned. In that prepareForDisplay (or whatever name you choose) method you can do whatever you like, e.g. hide _theView.

I would not recommend to abuse layoutSubviews for this as it is meant for a different purpose and will be called several times during the lifetime of a view, not just once as you want it to be. Yes you can save whether it was called before, but I would consider that a hack as well. Better create your own method to initialize the view in a way you want after you set it up correctly and call that.

Joachim Kurz
  • 2,875
  • 6
  • 23
  • 43
0

layoutSubviews will be call for all the views you can set you view as hidden there instead of awakeFromNib. If you are using xib then you can set the default hidden property.

Chirag
  • 259
  • 1
  • 8
0
private var layoutSubviewsCounter = 0
override func layoutSubviews() {
    super.layoutSubviews()
    if layoutSubviewsCounter == 0 {
        layoutSubviewsCounter += 1
        viewDidLoad()
    }
}

func viewDidLoad() {
    // your code here
}
Adam Smaka
  • 5,977
  • 3
  • 50
  • 55