A handful of my customers have reported a consistent freeze in my app (smells like either a thread deadlock or an infinite recursion to me). It's working properly for most people, but if 3 people are reporting it to me that says to me that probably 300 are experiencing it but staying quiet.
It happens every time they take a certain kind of action. But it never happens to me so I can't figure out what is breaking.
No crash is happening, so I'm not getting any reports via Firebase.
It doesn't appear to be related to their data, because they can have someone else use a different device, login to their account, download all of their data, and then successfully do the thing that freezes 100% of the time on their original device.
I've got one of these customers set up on TestFlight so I can send them test versions of the app with some debug collection code. I created my own version of a tracelog and write a line to a file whenever I start/end a function. I've added those tracelog calls to a bunch of methods and classes (but not all).
The action that causes the freeze is when they tap Edit on a record. What's supposed to happen is that I modally present a nav controller containing an EditBlahViewController.
The trace logs show that the EditBlahViewController gets through viewDidLoad, viewWillAppear, two rounds of viewWillLayoutSubviews/viewDidLayoutSubviews... but then never gets to viewDidAppear.
I've tried updating more and more functions/classes with the tracelog calls, but I can't find any infinite recursions. I've added tracelogs to all calls involving dispatching to other threads (especially synchronous dispatches to the main thread) but I don't see any deadlocks. Every dispatch to main starts and ends properly and then goes on to the next thing.
User is on iOS 16.6.1 with an iPhone 12.
I don't know what else to try. How can I debug this at a distance and figure out where the problem is?
This might be a bug in iOS 16/17 (all the users reporting the problem were on iOS 16.x).
When I was running iOS 16 on my sim and using the iOS 16-compatible version of Xcode, the freeze was never happening to me. iOS 17 got released along with a new version of Xcode, so I updated my Xcode to the new version (I was using the latest one before this as well). Once I did that, I started getting the UI to freeze up for me in the simulator! Woo!
Now that it was happening to me, I was able to run Instruments and track the stacktrace where the UI was locking up more precisely. I got a slightly different stacktrace which referenced a UICalendarView before the UICollectionView stack frames. (I forgot to capture a copy to paste here.) I wasn't familiar with UICalendarView but it appears to be a new replacement for UIDatePicker.
I finally found that viewWillLayoutSubviews was being called over and over, forever. I wasn't changing the size of anything in my UI during those calls... but deep in the iOS code, it was. Something in the UICalendarView code was making some kind of layout change every time layoutSubviews was called, so the system would call viewWillLayoutSubviews again and again, forever because something kept changing.
My UIDatePicker would start off-screen in my storyboard layout and then when it was needed, I would change the constraints in my layout to be smaller and that would cause the UIDatePicker to slide onto the screen.
The only workaround that I found to avoid this weird iOS bug, was to remove the UIDatePicker from my storyboard and then create one in code instead. And instead of doing it during initial creation of the view, I deferred the creation until just before I was going to show the UIDatePicker. And then whatever tickled the weird bug in UICalendarView just didn't happen.