viewDidLoad for UIView?

2019-04-03 04:13发布

问题:

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.

回答1:

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.



回答2:

Try

-awakeFromNib method

Or in xib set the view property hidden for your subview



回答3:

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:

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


回答4:

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.



回答5:

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.



回答6:

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

func viewDidLoad() {
    // your code here
}