I everyone,
I'm facing a strange issue with UIKit, that I'm not able to reproduce at every app launch. The problem is very simple: I have a main ViewController
and a child ViewController
that contains a UIScrollView
. You can see it as the following image:
My code to add the child controller is pretty simple:
private func configureKeyboard() {
guard let keyboardViewController = keyboardViewController else { return }
addChild(keyboardViewController)
keyboardContainerView.addSubview(keyboardViewController.view)
keyboardViewController.didMove(toParent: self)
keyboardViewController.view.translatesAutoresizingMaskIntoConstraints = false
keyboardContainerView.topAnchor.constraint(equalTo: keyboardViewController.view.topAnchor, constant: 0).isActive = true
keyboardContainerView.trailingAnchor.constraint(equalTo: keyboardViewController.view.trailingAnchor, constant: 0).isActive = true
keyboardContainerView.bottomAnchor.constraint(equalTo: keyboardViewController.view.bottomAnchor, constant: 0).isActive = true
keyboardContainerView.leadingAnchor.constraint(equalTo: keyboardViewController.view.leadingAnchor, constant: 0).isActive = true
}
But the line keyboardContainerView.addSubview(keyboardViewController.view)
seems to cause a crash:
Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named _UIScrollerImpContainerView because no class named _UIScrollerImpContainerView was found; the class needs to be defined in source code or linked in from a library (ensure the class is part of the correct target)'
So it seems like the scrollView is the cause of the crash. The stack show me that it seems to be falling on init(coder:)
.
Here is the way I'm instantiating my KeyboardController
. The controller itself is initiated on a Coordinator during the scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
:
class func controller(dataSource: KeyboardDataSource,
stackEditor: StackEditor,
onOperationTouch: @escaping (_ operation: CalculatorOperation) -> Void,
onShouldPresentSettings: @escaping () -> Void) -> KeyboardViewController {
let controller: KeyboardViewController = UIStoryboard(name: "KeyboardViewController", bundle: nil).instantiateInitialViewController() as! KeyboardViewController
controller.dataSource = dataSource
controller.stackEditor = stackEditor
controller.didTouchOperation = onOperationTouch
controller.shouldPresentSettings = onShouldPresentSettings
return controller
}
This crash kinda reminds me the crash we had with UITextView on as earlier version of Xcode that can cause a crash. I'm calling configureKeyboard
on viewDidLoad()
. Putting it on viewDidAppear()
doesn't fix the issue. I should also say that Catalyst is enabled on the app. But I only see this crash on the iOS app. Works perfectly on the Mac.
Sometimes, cleaning build folder and deleting the app seems to fix the issue. But I'm scared of deploying a version on the AppStore with such a random crash. This happen on a real device too. So probably not a simulator issue.
Also, the Storyboard file of the KeyboardController
is correctly associated to the iOS app target. Nothing on Apple Developer's forum. I'm out of idea.
Does someone encountered some familiar issue ?
Thanks in advance for your help.
After much test, I noticed that displaying the storyboard with the Mac Catalyst traits caused the issue. When compiling the app, I had to switch the storyboard to an iPhone or iPad traits. Never has the issue again after that.