Luda
Luda

Reputation: 7068

viewDidLoad for UIView?

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.

Upvotes: 30

Views: 20022

Answers (6)

Adam Smaka
Adam Smaka

Reputation: 6393

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

func viewDidLoad() {
    // your code here
}

Upvotes: 0

Joachim Kurz
Joachim Kurz

Reputation: 3070

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.

Upvotes: 2

Segev
Segev

Reputation: 19303

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

Upvotes: 6

Chirag
Chirag

Reputation: 259

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.

Upvotes: 0

Rebecca
Rebecca

Reputation: 653

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.

Upvotes: 25

Lithu T.V
Lithu T.V

Reputation: 20021

Try

-awakeFromNib method

Or in xib set the view property hidden for your subview

Upvotes: 27

Related Questions