Factory closure

Hello, can you explain in more details the difference in the init method between onboardingViewControllerFactory and LaunchViewController from 74 page. What is the difference? Why not to use method like makeLaunchViewController in case of onboardingViewController? It is not clear for me why to use this escaping closure instead. LaunchViewController and OnboardingViewController are all have transitive dependencies.

init(viewModel: MainViewModel,
launchViewController: LaunchViewController,
// Closure that creates an OnboardingViewController
onboardingViewControllerFactory:
@escaping () → OnboardingViewController,
// Closure that creates a SignedInViewController
signedInViewControllerFactory:
@escaping (UserSession) → SignedInViewController)

In the book you mentioned that it is important to give object under construction the ability to create multiple instances of dependencies from outside - to invoke a factory method multiple times. But why should we do this? According to project - MainViewController is initialized once and no new OnboardingViewControlled are needed in this case. Please clarify this problem.

@rcach @jab2109 Can you please help with this when you get a chance? Thank you - much appreciated! :]

According to what I understand.

The OnboardingViewController is only created if the UserSessionRepository can’t load the user session. If there was a session you need to create the SignedInViewController. So if you would pass an instance of OnboardingViewController instead of a closure, you will hold in memory a ViewController that may not be needed. Same case for SignedInViewController.

4 Likes

Thank you. I have enabled debug mode in xcode and now it is clear for me.

I have created one simple example in playground. May be it will be useful for somebody.

import UIKit

class DatabaseManager{

let databaseName:String
    init(databaseName:String){
    print("init db manager")
    self.databaseName = databaseName
    
}
deinit {
    print("deinit db manager")
}

}

class BusinessManager{

var dbManager: DatabaseManager?

//factory
let makeDBManager: () -> DatabaseManager


init(databaseManagerFactory:@escaping ()->DatabaseManager){
    print("init Business Manager")
    self.makeDBManager = databaseManagerFactory
}
public func presentDBManager(){

print(“start presenting DB manager”)
let presentedDBManager = makeDBManager()
print(“end presenting DB manaeger”)
}
}

func makeDBManager() → DatabaseManager {
print(“makeDBManager”)
return DatabaseManager(databaseName: “test”)
}

let dbManagerFactory = { () → DatabaseManager in
print(“inside dbManagerFactory”)
return makeDBManager()
}

var bm = BusinessManager(databaseManagerFactory: dbManagerFactory)

bm.presentDBManager()
print(“—”)
bm.presentDBManager()

Result will be

init Business Manager
start presenting DB manager
inside dbManagerFactory
makeDBManager
init db manager
end presenting DB manaeger
deinit db manager
---
start presenting DB manager
inside dbManagerFactory
makeDBManager
init db manager
end presenting DB manaeger
deinit db manager

So everytime we call businessManager method presentDBManager we automatically create databaseManager. This is used for short-lived dependencies.

1 Like

@ashitikov Thank you for sharing this - much appreciated! :]