After upgrading to Xcode 11.3.1 we noticed that our app started to crash on some devices when opening. It happens on different iOS versions and iPhone models. However on some devices with the same iOS version or iPhone model the app works fine.
When installing an earlier build of the app on these devices (that was build with an earlier Xcode version) the crash does not occur.
While debugging we found out that the crash occurs when trying to unwrap an Optional
when using the presenter of our login module. This presenter has a value when created and is assigned but after setting our rootViewController
in the AppDelegate window.rootViewController = navigationController
the execution jumps to the viewDidLoad()
function shown below at which point the presenter is nil
.
class LoginViewController: LoginPasswordResetViewController {
var presenter: LoginPresenterProtocol!
override func viewDidLoad() {
super.viewDidLoad()
updateUI(model: presenter.loadViewModel())
presenter.viewDidLoad()
}
}
Relevant code in AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let env = Environment()
if let app = UIApplication.shared.delegate as? AppDelegate,
let window = app.window,
let loginVC = LoginModule().createModule(moduleData: LoginModuleData(env: env),
service: LoginService(env: env),
storageService: LocalStorageService(env: env)) {
let navigationController = UINavigationController(rootViewController: loginVC)
window.rootViewController = navigationController
window.makeKeyAndVisible()
}
return true
}
I tried using the SceneDelegate.swift mentioned here Set RootViewController iOS 13 to set the RootViewController with no luck.
Any ideas on what could be the cause of this issue?
Additional info:
The createModule
function initializes and sets the presenter
:
func createModule(moduleData: LoginModuleDataProtocol, service: LoginServiceProtocol, storageService: LocalStorageServiceProtocol) -> LoginViewController? {
guard let viewController: LoginViewController = UIStoryboard.viewController(from: self) else {
return nil
}
let presenter = LoginPresenter()
let interactor = LoginInteractor()
let router = LoginRouter()
// VC
viewController.presenter = presenter
// Presenter
presenter.viewController = viewController
presenter.interactor = interactor
presenter.router = router
// Interactor
interactor.presenter = presenter
interactor.dataManager = LoginDataManager(data: moduleData, service: service, storageService: storageService)
// Router
router.viewController = viewController
return viewController
}
After creating the module, the loginVC
variable has the presenter
value as it should but as soon as we assign window.rootViewController = navigationController
the value of presenter
is nil
.