Reputation: 1666
A crash appears to this :
navigationController.view.layoutIfNeeded()
log : fatal error: unexpectedly found nil while unwrapping an Optional value
The crash appears for the first launch of the app (after the xcode build), and when my user disconnect and reconnect from his account. If i relaunch the app with an user already connected it will be ok.
Full function code :
func prepareControllers(){
homeTabs = [homeView, teamView, rankView, generalView]
for view in homeTabs{
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ABMainViewController.didTapTab(_:))))
}
mainControllers = [
UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "home") as! ABHomeViewController,
UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "teamController") as! ABTeamViewController,
UIStoryboard(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "leaderboardController") as! ABLeaderboardViewController,
ABInformationViewController(nibName: "ABInformationViewController", bundle: Bundle.main)
]
var previousController: UINavigationController? = nil
for viewController in mainControllers{
viewController.delegate = self;
let navigationController = UINavigationController(rootViewController: viewController)
navigationControllers.append(navigationController)
navigationController.view.frame = scrollView.bounds
navigationController.setNavigationBarHidden(true, animated: false)
navigationController.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(navigationController.view)
scrollView.addConstraint(NSLayoutConstraint(item: navigationController.view, attribute: .top, relatedBy: .equal, toItem: scrollView, attribute: .top, multiplier: 1, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: navigationController.view, attribute: .height, relatedBy: .equal, toItem: scrollView, attribute: .height, multiplier: 1, constant: 0))
scrollView.addConstraint(NSLayoutConstraint(item: navigationController.view, attribute: .width, relatedBy: .equal, toItem: scrollView, attribute: .width, multiplier: 1, constant: 0))
if(previousController != nil){
scrollView.addConstraint(NSLayoutConstraint(item: navigationController.view, attribute: .left, relatedBy: .equal, toItem: previousController!.view, attribute: .right, multiplier: 1, constant: 0))
}else{
scrollView.addConstraint(NSLayoutConstraint(item: navigationController.view, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leading, multiplier: 1, constant: 0))
}
navigationController.view.layoutIfNeeded() // CRASH HERE
previousController = navigationController
}
scrollView.addConstraint(NSLayoutConstraint(item: scrollView, attribute: .trailing, relatedBy: .equal, toItem: previousController!.view, attribute: .trailing, multiplier: 1, constant: 0))
}
In the debugging navigator :
0x102b691f8 <+116>: bl 0x102a5cb80 ; function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper from @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to @callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> (@out ()), Argument Types : [@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic specialization <preserving fragile attribute, ()> of Swift.StaticString.withUTF8Buffer <A> ((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
-> 0x102b691fc <+120>: brk #0x1 //HERE
is there a way to found where is this unwrapping value ? If someone have an idea, how can i solve it or how can i debug it more clearly. Thank's !
Upvotes: 0
Views: 4965
Reputation: 19
As Eperrin95 said maybe you are trying to layout something that doesn't exists yet. The layout methods should be called after viewDidAppear
or at least viewWillAppear
.
Upvotes: 1
Reputation: 654
Log say that one of your instance in navigationController.view.layoutIfNeeded()
is nil. Means that either navigationController
or view
is nil.
All views of a controller is nil before the method viewDidLoad
is called. Or, in your code, your instantiate the UINavigationController
and call it's main view directly after that.
If you really want to call layoutIfNeeded
method, subclass UINavigationController
and call the method in viewDidLoad
, viewWillAppear
or viewDidAppear
, even if I think you don't have to call it if your constraints are well implemented
class CustomNavigationController: UINavigationController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.view.layoutIfNeeded()
}
}
Upvotes: 0