user6631314
user6631314

Reputation: 1966

Avoiding fatal crashes

I have been debugging an app for a while and am ready to upload it to app store. However, I still get occasional crashes that are hard to duplicate or debug--for example when pushing buttons in weird sequences. If I write these sequences down, I can debug but inevitably it happens when I haven't written it down and these can be difficult to replicate.

I know I need to just call it a day and leave future bug fixes for next release. I have removed all the abort() statements I had in testing. However, occasionally rather than getting a crash that lets you just close the app and reopen, I get one that makes it impossible to open the app without reinstalling. For example, this just happened, with a

'NSGenericException', reason: '*** Collection <__NSCFSet: 0x174a41b90> was mutated while being enumerated.'

This resulted from switching VCs during a background sync to the cloud.

I can live with crashes where you just need to reopen but not with ones that render the app unusable. Are there any guidelines for types of crashes to help you focus on the really fatal ones?

Or is there anything you can do to keep crashes from bricking app?

Upvotes: 1

Views: 68

Answers (1)

Rob
Rob

Reputation: 437582

You should just fix this problem. Since you have this crashlog with that error message, you know which method can raise the problem, so you've got a good head start on fixing it, even if the problem manifests itself inconsistently and/or in a variety of ways.

But the occasional crash may not seem like too much of an inconvenience to you, but it is the quickest way to 1-star reviews and unhappy customers. I suspect you will quickly regret distributing an app with known, easily reproduced crashes.

But, a few observations:

  1. It sounds like your background update process is mutating your model objects used by the main thread.

    • If possible, I'd suggest being careful to simply do not change any of your model objects in the background thread, but rather populate a local variable and when you're ready to update the UI accordingly, dispatch both the model update and UI refresh to the main thread.

    • If you cannot do this for some reason, you have to synchronize all interaction of model updates with some mechanism such as locks, GCD serial queue, reader-writer model, etc. This is slightly more complicated approach, but can be done.

  2. I would advise temporarily editing your target's "scheme" and turn on the thread sanitizer:

    enter image description here

    It may possibly help you identify and more easily reproduce these sorts of problems. And the more easily you can reproduce the problem, the more easily you will be able to fix the issue.

  3. You say:

    Or is there anything you can do to keep crashes from bricking app?

    It sounds like the "save" operation is somehow leaving the results in persistent storage in an internally inconsistent manner. Any one of the following would help, though I'd suggest you do all three if possible):

    • At the risk of repeating myself, fix the crash (it's always better to eliminate the source of the problem than try to program around manifestations of the problem);

    • Depending upon how you're saving your results, you may be able to employ an atomic save operation, so that if it fails half way, it won't leave it in an inconsistent state; we can't advise how you should do that without seeing code snippet illustrating how you're saving the results, but it's often an option;

    • Make sure that, if the "load" process that reads the persistent storage can fail, that it does so gracefully, rather than crashing; see if you can get it in this state where the app is failing during start-up, and then carefully debug what's going on in the start-up process that is causing the app to fail with this particular set of data in persistent storage. In the "devices" section, there is an option to download the data associated with an app, so you can carefully diagnose what's going on.

Upvotes: 3

Related Questions