I have been trying to debug this for several days now but I can't seem to understand how it happens. I might be missing some information on how child view controllers are called.
I have a map that opens a child view controller on longpress. This works most of the time. Sometimes though, the app crashes. The console tells me:
Fatal error: Attempted to read an unowned reference but object 0x283f3cf80 was already deallocated
Note that this does not happen most of the time. It is rare and sometimes I need to trigger the long-press many times until it comes up. This is why I cannot use breakpoints. To help me debug, I have added many prints starting from "CHECK 1" to "CHECK 16". These print in the correct order when everything works well. When it breaks, it breaks between "CHECK 14" and "CHECK 15".
I use this code to call my ChildVC:
let slideVC = TripOverviewVC(customer: myCustomer, route: myRoute, panelController: panelController!, annotationManager: annotationManager!, mapview: mapView!)
slideVC.view.roundCorners([.topLeft, .topRight], radius: 22)
slideVC.view.layer.zPosition = 15
print("CHECK 8")
add(slideVC)
print("CHECK 13")
let height = view.frame.height
let width = view.frame.width
slideVC.view.frame = CGRectMake(0, self.view.frame.maxY, width, height)
print("CHECK 14")
And this is my add(_ child) function:
func add(_ child: UIViewController) {
addChild(child)
print("CHECK 9")
view.addSubview(child.view)
print("CHECK 11")
child.didMove(toParent: self)
print("CHECK 12")
}
On my child VC, the viewWillAppear
prints "CHECK 10" which is called correctly. However, after the child has been added using my add function, I guess that viewDidAppear
should be called. But it never does. This is my viewDidAppear
:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("CHECK 15")
UIView.animate(withDuration: 0.3) { [weak self] in
let frame = self?.view.frame
let yComponent = UIScreen.main.bounds.height - self!.view.frame.height*0.5
self?.view.frame = CGRectMake(0, yComponent, frame!.width, frame!.height)
}
tmpOrigin = self.view.frame.origin
print("CHECK 16")
}
This means that something breaks between adding the child as a subview, and before it is displayed on the screen, which is exactly what I can see on my app. What I don't understand is: What is being called between the two steps? Have I misunderstood the view lifecycle?