I am reaching out to seek clarification on the usage of exit(0)
within an iOS application under specific circumstances, as I have not been able to find concrete guidance on this in the App Store Review Guidelines
Context of Our Application:
We are developing a mobile game using Cocos2d-JS (Cocos2d-x JavaScript bindings). The game is built in C++ with JavaScript used for game logic, and it runs on both Android and iOS.
Occasionally, due to an unrecoverable fatal JavaScript error (e.g., corrupted state or unexpected runtime crash), the game’s screen goes completely black. When this occurs, the rendering engine halts, user interaction becomes impossible, and the app enters a non-functional state. From this point, the only way to return to a working state is to manually terminate and relaunch the app.
We are exploring a user-friendly solution where, upon detecting such a critical failure, we present a native UIAlertController to the user explaining the issue and informing them that the app needs to restart. Upon confirmation (i.e., tapping “OK”), we call exit(0)
to gracefully close the app, so the user can relaunch it in a working state.
Our Question:
Is it acceptable to use exit(0)
in this very limited and clearly explained context? The intention is to improve the user experience during unrecoverable fatal states that cannot be handled through standard UI or engine resets.
I understand that the use of exit(0) is
generally discouraged, but in our case:
-
The user explicitly initiates the exit via a native prompt.
-
The app is not quitting on its own or in response to a policy violation.
-
We are not using
exit(0)
to bypass App Review or circumvent system behavior. -
There is no mention in the App Review Guidelines explicitly stating whether or not
exit(0)
is disallowed in such edge cases.
Please confirm whether this approach aligns with Apple's policies, or suggest an alternative method for cleanly handling such irrecoverable errors on iOS?
Looking forward to your guidance.
Our Question: Is it acceptable to use exit(0) in this very limited and clearly explained context? The intention is to improve the user experience during unrecoverable fatal states that cannot be handled through standard UI or engine resets. I understand that the use of exit(0) is generally discouraged, but in our case:
SO, let me start from the general "policy" perspective, as the "rule" from App Review's perspective is actually pretty simple. The issue here is:
-
App Review can reject apps that crash.
-
From the end user perspective, a foreground app calling exit looks EXACTLY like it crashed.
...which means App Review can obviously reject your app if it calls exit and it looks like it crashed.
Note that the exit API itself is NOT the issue here. Indeed, your app already calls exit() or a regular basis without you realizing it. For example, when an app that's awake is force quit, what actually happens is that UIApplication executes the normal termination sequence (applicationWillTerminate, etc.)... and then calls exit(). That's never an issue because it obviously doesn't look like it crashed.
Looking at your specific case, let me first say that if you want a formal answer to a question like this, then you need to contact App Review directly. I've provided some general guidance based on my own experience in this area, but they're ultimately responsible for deciding whether or not something should be approved.
Moving to your case:
Occasionally, due to an unrecoverable fatal JavaScript error (e.g., corrupted state or unexpected runtime crash), the game’s screen goes completely black. When this occurs, the rendering engine halts, user interaction becomes impossible, and the app enters a non-functional state. From this point, the only way to return to a working state is to manually terminate and relaunch the app.
The right answer here is that you should fix your engine so this either doesn't happen or self recovers. If you can't do so, then there isn't really any "right" answer here. That is, listing the options, your app could:
-
Simply hang on that black screen.
-
Loop posting a dialog explaining that your app is broken and will need to be restarted.
-
Post a dialog and call exit() when the user approves it.
...but none of those is really "better" than the other in any really fundamental way and ALL of them could cause your app to be rejected. Yes, #2 is better than #1 and, arguably, #3 is better than #2. That doesn't change the fact that your game has failed, which is what App Review is actually concerned about.
The real review issue here isn't really about what you're doing, it's about how often this happens. A common issue means they can't properly review your app, while a very rare issue isn't really any different than any other app crash/failure.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware