ViewDidLoad being called before initWithNibName?

2020-07-08 02:56发布

问题:

I'm having the strangest error, and i hope someone could help me. Here is the code when I create a view controller and push it to navigationController. the problem is passing the random variable to the new view controller. I tried passing it in the init method and also passing it with the line commented below.

    MultipleBet *multipleBet = [[MultipleBet alloc] initWithMaxNumber:numbers andMaxStars:stars andRandom:self.random];
    NSLog(@"RANDOM1: %d", self.random);
    //[multipleBet setRandom:self.random];

    UIBarButtonItem *backButton = [[[UIBarButtonItem alloc] init] autorelease];
    backButton.title = @"Voltar";
    self.navigationItem.backBarButtonItem = backButton;
    [self.navigationController pushViewController:multipleBet animated:YES];

    [multipleBet release];

However when i access the random variable in the viewDidLoad of the MultipleBet, it's always FALSE.

here is the code of the MultipleBet:

- (id)initWithMaxNumber:(int)maxNumbers andMaxStars:(int)maxStars andRandom:(BOOL)isRandom {
    self = [super initWithNibName:@"MultipleBet" bundle:[NSBundle mainBundle]];
    ...

    self.random = isRandom;
    NSLog(@"RANDOM2: %d", self.random);
    NSLog(@"RANDOM2.1: %d", isRandom);

return self;
}

and here is the code of the viewDidLoad:

- (void)viewDidLoad {
   [super viewDidLoad];


    NSLog(@"RANDOM2.2: %d", self.random);

}

i declare the variable and property like this:

BOOL random;
@property (nonatomic) BOOL random;

and the output is always:
RANDOM2.2: 0
RANDOM2: 1
RANDOM2.1: 1
RANDOM1: 1

Why is the NSLog from the viewDidLoad being outputted before all the others? it should be the last... Could it be because of my custom init method? I call the [super init], so it shouldn't be a problem...

回答1:

viewDidLoad and init* methods are not guaranteed to execute one after the other. Code in your init* methods may cause the view to load, hence viewDidLoad will be called even if the init* method has not finished.

Most likely, some code in the part you omitted is causing the view to load. If you will show us that part, maybe we can point it out. Or, you can also move the self.random = isRandom; line as the first line inside your if (self) block and see if that works out. This way, whatever is causing the view to load will be executed after you have assigned self.random.

- (id)initWithMaxNumber:(int)maxNumbers andMaxStars:(int)maxStars andRandom:(BOOL)isRandom {
    self = [super initWithNibName:@"MultipleBet" bundle:[NSBundle mainBundle]];
    if (self) {
        // do this first
        self.random = isRandom;
        NSLog(@"RANDOM2: %d", self.random);
        NSLog(@"RANDOM2.1: %d", isRandom);

        // do the other code after
        ...
    }

    return self;
}


回答2:

I bumped into this problem. I was calling a method or property with self in the selector, e.g. self.bannerView.frame or [self createBannerView] from within the init* method. Obviously, self is not completed initialization at that point, so apparently Apple has some code that will call viewDidLoad before accessing properties or methods. My solution was to move the calls out of init and place them in viewDidLoad.



回答3:

Probably in the part you left out (...) you are causing the view to load in some way. I.e., calling a setter in the initializer might cause you to do a [self.tableView reloadData] or something.