Mason
Mason

Reputation: 7103

View Controllers, Dependency Injection, and init/viewDidLoad

I've read a bunch of answers on SO already, but I'm a little confused.

I have a tab bar controller subclass I created, and in its viewDidLoad, I'm creating each of the view controllers. However, I have a dependency that I'm passing into the parent, and in turn into the view controller for each tab. I'm passing that dependency in with a custom init method (NS_DESIGNATED_INITIALIZER declared for it in the header). However, it looks like [super init] triggers viewDidLoad directly, so the dependency isn't set properly when the other view controllers are created.

Here's my custom init method:

- (instancetype)initWithSession:(T2Session *)session
{
    self = [super init];

    if (self) {
        _session = session;
    }

    return self;
}

I'd like session to be set by the time I create the view controllers, but I'm sort of confused about what the best way to do this is. Any advice is much appreciated. Thanks in advance!

Upvotes: 0

Views: 351

Answers (1)

MDMonty
MDMonty

Reputation: 363

I've come across this situation before.
You probably sat there (like me) wishing viewDidLoad didn't get called so soon.

Anyway, this is what I settled on:

- (instancetype)initWithSession:(T2Session *)session {

    if (self = [super init]) {
        self.session = session;
    }

    return self;
}

- (void)setSession:(T2Session *)session {
  _session = session;

  ... call the setup methods here, instead of viewDidLoad
}

At first I thought this breaks the golden rule of not calling self.xxxx from within an initializer.
However, I think that rule is only really relevant when calling methods on IBOutlets that may not have been wired up yet.
In this case, T2Session *session isn't a nib outlet.

Alternatively, if you prefer not to break that rule you could always remove the custom initializer .. and revert to using regular property-injection rather than constructor-injection. e.g.

T2Session *session = .....

MYTabBarController *tabBarController = [[MYTabBarController alloc] init];
[tabBarController setSession:session];

These are just my thoughts, hope it helps.

Upvotes: 1

Related Questions