Trying to debug a crash that a user is having that isn't showing up in our crash reporting tool or in our log files. Have a theory it might be down to memory pressure, but not sure if applicationWillTerminate will be called if iOS kills an app application in the foreground. We write to our log file in applicationWillTerminate but it apparently isn't being called during this crash.
If the app crashes, no lifecycle method is called reliably. Instead you can create & register a global exception handler which gets invoked in this case:
func exceptionHandler(exception: NSException) {
print("*** UNHANDLED EXCEPTION ***")
print(exception)
print("CALL STACK:")
print(exception.callStackSymbols.joined(separator: "\n"))
}
Register this function using NSSetUncaughtExceptionHandler, e.g. in your UIApplicationDelegate.application:didFinishLaunchingWithOptions::
NSSetUncaughtExceptionHandler(exceptionHandler)
System had to trigger applicationWillTerminate if it up to kill the app. However you can't be sure how much time you have to before app actually will be killed. Maybe it just not enough time to write the log. Before killing app due to memory consumption system should send memory warning. You can test last one by simulating memory warning on Simulator. If applicationWillTerminate didn't called then want terminated by system and you crash not related directly to memory consumption.
I created a saveState() method that uses UserDefaults to save certain settings at certain parts of my App. It works fine when I exit the App and return, but if I actually turn my (iOS) phone off, when I start the App again, the settings are not saved. In addition to those places where I call the saveState() method in the code, I also call saveState() in three AppDelegate functions: applicationWillResignActive, applicationDidEnterBackground and applicationWillTerminate. I have a loadState() function in viewDidLoad so any saved information will load at that time. Does anyone know what I am not doing re: saving/restoring settings when phone powered off?
When iphone off, AppDelegate's applicationWillTerminate
function Called when the application is about to terminate
how about use synchronize() after your saveState() called
In apple API https://developer.apple.com/reference/foundation/userdefaults/1414005-synchronize
Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk.
When setting up a WCSession in a watchOS app, does the WCSessionDelegate's sessionReachabilityDidChange: method always get invoked immediately after calling activateSession? From my testing this seems to be true but I am not finding any confirmation of this in documentation.
I ask because if I can rely on sessionReachabilityDidChange: being called immediately after activating the session, I can remove some redundant code from applicationDidBecomeActive that checks for a reachable session and sends some initial messages to the iPhone app.
Why not just call it yourself after you are done doing all your set up? That way you don't rely on any undocumented behavior, yet you don't have to duplicate code in two places
There are a few ways your app can launch:
User opens app
Push notification leads to opening of app.
What is the recommended design to know when to make a async network call to your server to fetch some data? For example, didFinishLaunchingWithOptions gets called at app launcht ime, so would it make sense to put that call in that function? What about putting the call in viewDidLoad of my root view controller? viewDidLoad only gets called once for load while viewWillAppear gets called too frequently.
What's a good pattern or design to handle both cases of app launch.
At some point in my application I have done this exit(0) which crashes my app. But I haven't figured out what method gets called when this executes.
I've put messages in:
(void)applicationWillTerminate:(UIApplication *)application
(void)applicationDidEnterBackground:(UIApplication *)application
But none of this seem to get called! Any idea about what method is called when exit(0) is done?
From Apple's Human User Guidelines...
Don’t Quit Programmatically
Never quit an iOS application programmatically because people tend to
interpret this as a crash. However, if external circumstances prevent
your application from functioning as intended, you need to tell your
users about the situation and explain what they can do about it.
Depending on how severe the application malfunction is, you have two
choices.
Display an attractive screen that describes the problem and suggests a
correction. A screen provides feedback that reassures users that
there’s nothing wrong with your application. It puts users in control,
letting them decide whether they want to take corrective action and
continue using your application or press the Home button and open a
different application
If only some of your application's features are not working, display
either a screen or an alert when people activate the feature. Display
the alert only when people try to access the feature that isn’t
functioning.
If you've decided that you are going to quit programmatically anyway...
In C, exit(0) will halt execution of the application. This means that no delegate methods or exception handlers will be called. So, if the goal is to make sure that some code gets called when the closes, even on a forced close, there may be another option. In your AppDelegate implement a custom method called something like -(void)applicaitonIsgoingAway. Call this method from within anywhere you want your exiting code to be called:
applicationWillTerminate
applicationDidEnterBackground
onUncaughtException
The first two are ones that you already mentioned in your question. The third can be a catch-all of sorts. It's a global exception handler. This next bit comes from a question on that very topic.
This exception handler will get called for any unhanded exceptions (which would otherwise crash your app). From within this handler, you can call applicaitonIsgoingAway, just like in the other 2 cases. From the other question that I mentioned above, you can find an answer similar to this.
void onUncaughtException(NSException* exception)
{
[[AppDelegate sharedInstance] applicationIsgoingAway];
}
But in order for this to work, you need to set this method up as the exception handler like so...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&onUncaughtException);
//There may already be more code in this method.
}
Now, you can quit the app programmatically by calling NSAssert(FALSE, #"Quitting the app programmatically."); As long as there is no other exception handler in place to catch this, your app will begin to crash, and your exception handler code will be called. in-turn calling applicationIsGoingAway.
When you call exit(0) you immediately terminate your application. 0 is a status code which means successful termination.
No other method is called, you application just dies. As a result end user may think app is just crashed.
Apple discourages you to call exit anywhere.
exit(0) is a C function that terminates your app's process therefore none of the application delegates methods will be called, the app will be killed immediately. Apple recommends strongly against your app quitting because it appears broken to the user.
There is no Apple-supported method to terminate your application programmatically. Calling exit is certainly out of the question. This causes all sorts of bugs (for example the multitasking switcher will break badly) as well as simply being wrong.
If you are trying to disable multitasking, you can do this with the UIApplicationExitsOnSuspend key in your Info.plist file (the title for the key is "Application does not run in background").
Other than that, it's up to your users to press the home button to close your application.
these methods will be called but you cannot use exit(0) you will need to press the back button to close your app then these methods will be called