objective c - Over-released object iOS app crash


Keywords:ios 


Question: 

My app is crashing with the last message in the device console:

objc[5105]: Cannot form weak reference to instance (0x10801ec00) of class UIPageViewController. It is possible that this object was over-released, or is in the process of deallocation.

Randomly app also crashed with the same error message but UINavigationController instead of UIPageViewController. A bug is reproducible on the simulator and physical devices (iOS 11.2.5).

Profiling with "Zombie" template in Instruments did not give any valuable information. I found that outdated guide useful:


My answer might not fix your issue but I hope it will help to track it. Additionally, I'll appreciate if someone explains why ARC fired on a different thread.


1 Answer: 

By subclassing UIPageViewController and setting breakpoint in it's dealloc I found that it's not executed on the main thread.

don't do this in production - only play around when debugging

Synchronously removing its view from view hierarchy on the main thread did fix the issue. I have no view controller container responsible for that:

- (void)dealloc {
    dispatch_sync(dispatch_get_main_queue(), ^{
        [self.view removeFromSuperview];
    });
}

However it was not even about the view, while just delaying execution was enough to fix the crash, and the view will be cleaned together with its superview.

- (void)dealloc {
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"%@", self);
    });
}

View controllers were stored in the array, and I knew that when this array was destroyed, view controllers are as well. I checked on which thread object holding the only one reference to this array is destroyed, and it is main thread. ARC should release objects on same thread where the last reference to the object was removed, but that is not the case in my app.


How did I fix my issue: I don't why it was so. I did not search for a reason anymore when I found that issue will also disappear when I manually remove reference to the array, right before removing the last reference to its owner.