-1

I'm new to iOS development. I need to inject my UIViewController with injected dependencies and services rather than creating them inside init() or viewDidLoad() methods. Something to look like this:

// Initialize View Controller
let viewController = ViewController()

// Configure View Controller
viewController.requestManager = RequestManager()

My questions are:

  1. Is that possible in iOS or not ?
  2. Where do I create the dependencies and UIViewControllers ??
  3. How MyUIViewController does look like, should I use init() method ?

Note 1: I don't to use any kind of containers. I need to use pure man DI.

Note 2: What am talking about looks like IControllerFactory in ASP.NET MVC.

Nadeem Khoury
  • 886
  • 6
  • 18
  • 1
    I have no idea what you mean by "dependency injection". But the code you showed is legal, so what's the problem? – matt Nov 03 '16 at 16:09
  • where do I insert it ? – Nadeem Khoury Nov 03 '16 at 16:10
  • Wherever you want. Your code creates a view controller so you would do it when you create the view controller. – matt Nov 03 '16 at 16:11
  • can you please explain more ? – Nadeem Khoury Nov 03 '16 at 16:12
  • Can you tell me when the ViewController created in ios ?? and who is responsible of creating the view controllers ? – Nadeem Khoury Nov 03 '16 at 16:13
  • A view controller is an object like any other. It is created because it is instantiated, which is what you are doing when you say `ViewController()`. If you want to be responsible for creating it, you can be. Many people allow the storyboard and the nib-loading mechanism to be responsible, but no law says you have to do that. – matt Nov 03 '16 at 16:16
  • "Dependency injection" is just a fancy name for one of the most used patterns in programming. I would assume you wanted something like delegates or a Factory pattern? – Sulthan Nov 03 '16 at 16:58
  • 1
    It sounds like you haven't bothered to read any of Apple's documentation - this is fundamental to iOS development. Try working through this https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/index.html, and then come back if you have more questions. – Ashley Mills Nov 03 '16 at 17:09
  • @Sulthan Yes exactly this what I want. – Nadeem Khoury Nov 03 '16 at 17:12
  • @AshleyMills Actually I have read a complete book for iOS programming called big nerd ranch ios programming 5th, but it didn't talk about this issue. – Nadeem Khoury Nov 03 '16 at 17:13
  • 1
    @NadeemKhoury Factory pattern is not something you would use in Objective-C/Swift mostly because there are multiple better solutions. – Sulthan Nov 03 '16 at 17:15

3 Answers3

3

If you are using UIStoryboardSegue to transition to a new view controller, you can do setup, including dependency injection, in the -prepareForSegue: callback. This happens after the view controller is loaded from the storyboard and initialized, but before any view is loaded. Example:

- (void)prepareForSegue:(UIStoryboardSegue *)segue {
    MyViewController * vc = (MyViewController *)segue.destinationViewController;
    vc.injectedProperty1 = [InjectedObject new];
    vc.injectedProperty2 = [OtherInjectedObject new];
}
jbelkins
  • 470
  • 3
  • 15
2

In order to be able to inject dependencies into a view controller you will have to subclass UIViewController and create a custom init function.

See this SO post as an example: how-do-i-make-a-custom-initializer-for-a-uiviewcontroller

So in your UIViewController subclass you would have a custom init, something like:

init(requestManager: RequestManager)
{
    self.requestManager = requestManager

    super.init(nibName: nil, bundle: nil)
}

and where you create a instance of MyUIViewController you would have:

let myRequestManager = RequestManager()
let viewController = MyUIViewController(requestManager: myRequestManager)
Community
  • 1
  • 1
Simo
  • 2,172
  • 3
  • 19
  • 23
2

The reason the BNR book didn't mention factory methods, is that iOS apps don't (generally) use them to create view controllers. If you're new to iOS development, and going down that route, you should probably think again about your app structure.

You are better off starting out with storyboards, and assigning properties in the prepare(for segue: UIStoryboardSegue) method of the presenting view controller. e.g.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let viewController = segue.destination as? MyViewController {
        viewController.requestManager = requestManager
    }
}

Although, of course you can override required init?(coder aDecoder: NSCoder)

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    requestManager = RequestManager()
}
Ashley Mills
  • 50,474
  • 16
  • 129
  • 160