How do I inject dependencies into an iOS view controller?

守給你的承諾、 提交于 2021-02-06 19:18:35

问题


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.


回答1:


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.




回答2:


Why not use NSNotificationCenter?

An NSNotificationCenter object (or simply, notification center) provides a mechanism for broadcasting information within a program. An NSNotificationCenter object is essentially a notification dispatch table.

You can add notification observer at both singleton or common one, and when you need to send messages, just post the right notification. Observers'll manage the action then.

More detail on NSNotificationCenter.




回答3:


Isn't this about getting the reference to the view controller object? If you are using storyboards, then the windows rootViewController or the segues used will give you the right view controller object.

i.e: Instance of the view controller when the app starts is

self.window.rootViewController

When you are segues to transition between scenes (view controllers):

[segue destinationViewController] or [segue sourceViewController]

If you are using xibs you could even use an external object(proxy object) from the interface builder to supply the model object. Only thing is you will have to take the nib instantiation into your own hands.




回答4:


Ideally at some point third party devs will be allowed to use their own constructors/initializers even when using storyboards.

Until then you could use setter/property injection and the mediator pattern, especially since you're used to best practices and loose coupling.

I've written about it here: http://cocoapatterns.com/passing-data-between-view-controllers/



来源:https://stackoverflow.com/questions/13169407/how-do-i-inject-dependencies-into-an-ios-view-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!