Crash due to IBOutlets as nil, viewController resolved in tableView:didSelectRowAt:, used DipUI
Daemon-Devarshi opened this issue · 1 comments
I tried DIP in a sample app, which has two view controllers:
EmployeesViewController
- contains list viewEmployeeDetailViewController
- detail view is loaded when a cell on previous list view is selected
I am setting up the dependencies using below code:
// CompositionRoot.swift
extension DependencyContainer {
static func configure() -> DependencyContainer {
return DependencyContainer { container in
container.register { EmployeesViewModel() as EmployeesDataSource }
container.register(tag: EmployeesViewController.storyboardIdentifier) { EmployeesViewController() }.resolvingProperties { container, controller in
controller.dataSource = try container.resolve() as EmployeesDataSource
controller.container = container
}
container.register { employee in EmployeeViewModel(employee: employee) as PresentableEmployeeInfo }
container.register(tag: EmployeeDetailViewController.storyboardIdentifier) { EmployeeDetailViewController() as EmployeeDetailViewController }
DependencyContainer.uiContainers = [container]
}
}
}
extension EmployeesViewController: StoryboardInstantiatable { }
extension EmployeeDetailViewController: StoryboardInstantiatable { }
I am trying to load EmployeeDetailViewController from tableView:didSelectRowAt:
function as shown below:
// EmployeesViewController.swift
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let employee = dataSource.employee(at: indexPath.row)
let employeeInfo = try! container.resolve(arguments: employee) as PresentableEmployeeInfo
// Below code works and does not crash in EmployeeDetailViewController-viewDidLoad
//let storyboard = UIStoryboard(name: "Main", bundle: nil)
//let detailViewController = storyboard.instantiateViewController(withIdentifier: "EmployeeDetailViewController") as! EmployeeDetailViewController
// Below code crashes in EmployeeDetailViewController-viewDidLoad due to IBOutlets as nil (if used in place of above code)
let detailViewController = try! container.resolve(tag: EmployeeDetailViewController.storyboardIdentifier) as EmployeeDetailViewController
detailViewController.employeeInfo = employeeInfo
navigationController?.pushViewController(detailViewController, animated: true)
}
Problem is - It crashes in EmployeeDetailViewController-viewDidLoad
due to nil IBOutlets. It works fine when I load the same view controller using standard functions.
Here is the link to its codebase - DIPSample.
Am I missing anything over here? Please suggest.
You are using Dip-UI in a wrong way. If you register view controller that should be created from storyboard you should not explicitly resolve it with container, you should create it in a usual manner - using a storyboard. Container then will resolve its dependencies with property injection. If you want to resolve view controller explicitly you should register it properly with UIStoryboard.instantiateViewController(withIdentifier:)
or with UIViewController.init(nibName:bundle:)
and view controller defined in xib.