How to get error reports of a freezing iOS app?

Viewed 1711

Recently I had an issue in my iOS app that caused the app to freeze. The UI was unresponsive and the user had to kill and restart the app to make it work again.

In Google's Play Console I see such issues as ANRs ('Application not responding' errors).

But in Xcode I don't get any reports unfortunately. Crashlytics also didn't show any reports.

Is it possible to somehow get some kind of report with a stacktrace similar to the ANRs in Google's Play Console?

Please note:

  • I know what caused the app to freeze in this specific issue and also how to debug and fix it. What I want is an error report in case the issue wasn't found during QA but it is occurring in a user session.

  • The freezing version was not published to App Store, only to TestFlight.

3 Answers

The reason for unresponsive UIs could be due to a number of reasons:

  1. One reason could be because of high load (running out of RAM, Swap Space). For detecting these scenarios (without crashing behavior) you need Application Performance Monitoring, for example with Firebase. The advantage with Firebase is you don't have to prompt for consent, so you get more data to detect hangs. The Xcode Organizer can provide Hang Rate metrics though if you have enough users who have consented to share their data (new in Xcode 11).
  2. Another reason could be due to logical errors in code. For example, a user triggers an unexpected app flow that was missed during manual testing. In these instances, it can be harder to narrow down but could be trackable with manual user testing beforehand e.g TestFlight. You can use In-App Feedback tools (users send you emails) to gather context about the issue or Instabug for screenshots and advanced feedback.
  3. The other reason could be because of deadlocks. If you use DispatchGroup for instance or DispatchSemaphores to queue network requests and the requests time out then that could also lead to suspended UI frames. I would look carefully at where you leave the dispatch group as well - all possible branches should have a dispatch_group_leave statement to avoid hanging on dispatch_group_wait.
  4. You can use the Thread State Trace Instrument to see whether system calls are blocking your main thread to debug this issue. The classic iOS dev advice is to only perform UI updates on the main thread and move all other logic to a background thread. This may not solve the root cause but does prevent hangs. The same logic applies for Core Data fetches, inserts, deletes, and updates. Move Core Data operations to background threads in network request callbacks as well.
  5. If you get crash reports, it's simple to diagnose an OOM error in a Crashlytics crash report for example (comes up in Insights). Heap corruption can also be inferred from crash reports, and while the metadata may not be the same for the same behavior, it could point you to a screen or action when you try and reproduce the bug.
  6. Watchdog Unresponsive App crashes can be intercepted to come up in crash reports if the user doesn't kill the app beforehand, but you mentioned the user killed the app so this may not be available.

There is no direct equivalent ANR error reporting for iOS apps, given that Hang Rates are only aggregated if enough sessions have been detected. You could do screen recording of app sessions (ServiceNow), but I don't advise it because it has privacy implications.

Crashlytics is unable to send abnormal terminations fired by the watchdog. I've researched this for Jetsam terminations. You will see them in the console logs. see this link for the watchdog crash iOS generates: Watchdog Unresponsive App. If there's a way to monitor the main thread for queued operations executing for too long, you could fire a fatal error ie fire a fatal before the watchdog terminates the app.

Do some research on MetricKit. It's new to iOS 13. There's a class called MXHangDiagnostic. You can use it in your app to monitor for hangs and report on them as you see fit.

Related