Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I inject dependencies into an iOS view controller?

My view controllers need to send messages to a couple of model objects. How do I obtain references to these model objects inside the view controller?

These model objects are "singletons" (in that there should only be one copy of them in the system at once) and they are used by multiple view controllers. So I can't instantiate them in the init method of each view controller.

I can't use constructor injection as the runtime chooses the init method that gets used to create the view controller.

I can't use "setter injection" as at no point (that I am aware of) do I have both a reference to the newly constructed view controller and references to the "singleton" model objects.

I don't want to turn the model objects into proper singletons and call a static method on them from the view controllers to retrieve the singleton instance, as this is a problem for testability. (Having the model objects as properties on the AppDelegate is essentially the same as doing this.)

I am using iOS 6 with Storyboards.

like image 666
Robert Atkins Avatar asked Nov 01 '12 00:11

Robert Atkins


People also ask

What is dependency injection in IOS?

Dependency Injection (DI) is a design pattern that decouples an object from the instantiation of its dependencies. An object doesn't need to know how to create its dependencies. Instead, we “inject” them to it.

Where do we use dependency injection IOS?

Dependency Injection is a software design pattern in which an object receives other instances that it depends on. It's a commonly used technique that allows reusing code, insert mocked data, and simplify testing.

Can we inject the dependency to individual action method of the controller?

You can take advantage of the ServiceFilter attribute to inject dependencies in your controller or your controller's action methods.


1 Answers

I've just dealt with the same problem. Since I'm using storyboards I don't instantiate my UIViewControllers, so I can't use "constructor injection". I must resign myself using setter injection.

My app root is a UITabViewController. Let's say it has two UINavigationControllers, having the first a AControllerView and the second BControllerView. In AppDelegate.applicationDidFinishLaunchingWithOptions you can retrieve the root controller this way:

UITabBarController *tabBarController = (UITabBarController *) self.window.rootViewController;

Then you can iterate through the controllers:

NSArray* viewControllers = [tabBarController viewControllers];
for (UIViewController *viewController in viewControllers) {
    UINavigationController *navigationController = (UINavigationController*) viewController;
    UIViewController *viewController = navigationController.topViewController;
    if ([viewController isKindOfClass: [AControllerView class]]) {
        AControllerView *a = (AControllerView*) viewController;
        // Inject your stuff
    }
    if ([viewController isKindOfClass: [BControllerView class]]) {
        BControllerView *b = (BControllerView*) viewController;
        // Inject your stuff
    }
}

Hope it helps.

like image 186
juanignaciosl Avatar answered Sep 23 '22 07:09

juanignaciosl