Some of the iOS users of my app (one with an iPhone 6 with iOS 9.3.2) report that upon Force Quitting the app, they will see a black screen with only the Apple logo and a restart bar, and their device will restart. My own devices do not reproduce this and I do not receive any crash reports, so I've been unable to track this issue down. The users are under the impression that their phone or the app has crashed.
STEPS TO REPRODUCE
Open the app
Press the home button on the iPhone and then let the app go into the background for about 20 minutes.
Reopen the app
Double-tap the home button and swipe to Force Quit the app
Some users are reporting seeing a black screen with just the Apple logo and a restart bar at this point.
I do have background location updates running on the app, as well as a background process. I have tried ending this background task when the app re-enters the foreground, but that does not prevent the "apple logo" screen appearing for the users who are already seeing this effect.
Though there was no stacktrace so it was difficult to identify, the below ended up being my problem. I'm documenting it in case someone else runs into something similar.
As mentioned originally, I am creating background processes. This is how I was using them:
Old way:
I declared this at the top of my location manager:
private var bgId: UIBackgroundTaskIdentifier!
then, inside locationManager(_:didUpdateLocations:), I included these lines:
self.bgId = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { _ in
UIApplication.sharedApplication().endBackgroundTask(self.bgId)
}
This was to keep the app alive in the background as long as possible as location readings came in. I thought that since I was using a single reference for bgId, the background tasks would be overwritten and only one would exist, no matter how often location updates came in.
New way:
First, I made bgId optional:
private var bgId: UIBackgroundTaskIdentifier?
Then, I replaced the earlier code snippet in locationManager(_:didUpdateLocations:) with this:
if self.bgId == nil {
self.bgId = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { _ in
if let bgId = self.bgId {
UIApplication.sharedApplication().endBackgroundTask(bgId)
self.bgId = nil
}
}
}
It's possible that iOS was actually creating a ton of background processes and not overwriting them as I had thought. If true, this approach creates far fewer processes.
After making this change, I no longer see the "respring" effect of the apple logo and restart bar when going through the procedure in my question.
Related
If I send my app to background by clicking the home button and wait a certain time (perhaps 1 or 2 hours).
What will happen if i tap on the app icon now?
Will the app relaunch or simply be brought from background to foreground?
Quick "prologue":
Welcome to the wonderful world of stack overflow (SO), I myself am rather new here, but found it much friendlier to use welcome you anyway!
Just in case you haven't: Before you ask a question please look around a bit on SO in case someone else has asked the same thing, but if you can't get your question answered from that, then you should of course ask your own question.
Answer:
This question has no definite answer, because it depends. When you tap the home button your app enters, as you've said, the background and is still running to a certain degree. However after done so, the apps life cycle is up to iOS (the devices operating system) to determine. iOS controls and checks memory and CPU usage (etc..) of the device, and if you start another activity while your app is in the background that makes the available memory and CPU etc of the device not sufficient, iOS will terminate any apps in the background to not waste those resources (or battery etc). If so your app will relaunch next time you tap on it.
Although if you don't do anything performance heavy it is more likely that iOS keeps your device running in the background.
I'm not sure about the exact conditions and such the iOS works on, but i would say its very likely your app will have gotten terminated and is relaunched after 1 or 2 hours "in the background". Additional conditions apply if the device is locked during that period.
For proper documentation of this i would recommend reading Apples documentation for handling App State Transitions and/or the api for UIApplicationDelegate on apples developer website. Where you can see what the different methods in the AppDelegate does and how they interact.
Edit (answer to comment):
A way to relaunch the app everytime it goes into background?
Hm, yes, but also no. I'm not 100% sure about this (never encountered that "wish" before), but you can do this in your AppDelegate: (It will basically crash your app, but beware that apple does not encourage you to crash your own app anywhere). Doing this might stop the app from passing through apple store review process (i.e. your app might not be accepted to the App Store).
func applicationDidEnterBackground(_ application: UIApplication) {
exit(0)
}
Check out the answer to these post for a bit more information: call exit(0) in iphone app , objc - Proper way to exit iPhone application?.
Personally I would recommend you to work around it and don't do this. Also remember that when your app will enter the background applicationWillResignActive will be called and when the user opens it again, applicationDidBecomeActive gets called so you can do a reload or something from there if you want to refresh any data.
Whenever we press the home button in our device, the application releases the currently being used memory and moves to background stage. However, when we press this application app icon again it brings the app on top of the iPhone screen and occupies memory again. This is definitely not the relaunch because relaunch depends upon the UIApplicationDelegate method
didFinishLaunchingWithOptions. When we are switching app from background to foreground then applicationWillEnterForeground method fires.
For better understanding, the following link might be useful
iOS Application Life Cycle
I am new to IOS development. I am still confused about data lifecycle inside the UIViewController. If I had a property called "userData" and I identified it as following
let userData : UserData! {
didSet {
// do something
}
}
and I used this data to handle click events later. What could happen if the app went to background then -say after 1 hour- the user reopened the app and found the page still displaying the content, then he clicked a button inside page. I am not sure if userData will be kept or the page lost it when it went to background!?
My app crashes when I come later and open it, but I am not sure if that's because of identifying variables like this or not
The term background is confusing. Apple generally uses it to mean a state where your app is still getting processor time but another app is front-most. You have to ask if you want more than a few seconds of background time when the user hits the home button.
If the user presses the home button and then swaps to another app your app gets a few seconds of background time to save it's state, and then it moves to the "suspended" state, where it is still in memory, but no longer gets processor time.
Once you've been suspended, if the user switches back to your app while it's still in memory you get a resume message and then you continue running, with everything that was in memory still in memory.
However, once you've been suspended your app can be terminated at any time after that without any warning. That's why you have to save your app state when you get suspended.
If you do get terminated then the next time the user selects your app you get re-launched. You are usually expected to restore state and make it look like the app simply picked up where it left off, but it is a cold launch.
If you are crashing after your app is resumed (not terminated) then you might need help debugging that crash.
I am accessing location services as 'always', i know all the changes made by apple in iOS 11. i updated my plist as required( added new key). I calling stopUpdatingLocation as soon as application goes to the background, but this blue still stays there saying your application is using location in the background. Top of that filled location icon in status bar changes to outlined location icon also. I am using Mapbox SDK as well. Is it a bug with iOS 11 or am i missing something? Just to give background information, i am fully aware how location services works. i tried almost all solutions to remove that blue bar, but it seems it is not happening.
I tried self.locationManager.allowsBackgroundLocationUpdates = false, self.locationManager = nil, self.locationManager.delegate = nil but nothing is helping.
It will be great if anyone can help me with this.
iOS 11 Beta release 5 has removed the unnecessary and intrusive Blue banner that displays for apps that used the location of the iPhone. Displaying the Blue bar for background location use is left to the app developer through a property.
#property(assign, nonatomic) BOOL showsBackgroundLocationIndicator
The users of the apps with location features are prompted to allow location permission first at the time of installing an app and then periodically prompted for apps that use location in the background continuously. The location use indicator arrow with three different shades is another mechanism for users to know if the location service is in use. Therefore an always appearing blue banner is unnecessary and Apple has recognized it.
I am developing an Apple Watch2 App. My app stops running after a few seconds the screen turns into black but I want my app to run on the screen even after the screen turns into black. So that the user can see my app anytime on the screen by not tapping to the app icon again.
I tried to add a timer and then an animation and also made dynamic UI changes to avoid my app to stop running but it didn't work - after a few seconds the screen turns into black, the app stops and the main watch clock screen comes into display.
I saw that it is possible to do this functionality in "Apple Workout App". When the user starts a timer, even if the screen turns into black, the app doesn't stop running so the user checks the timer anytime she/he wants. So please let me know how I can get this functionality?
Thanks,
E.
You can't control this from your app; The user selects the behaviour for their watch using the Apple Watch app on their phone. They can select "Show watch face" (the default) or "Resume Last Activity". They can also select how long the display stays on for on a tap; either 15 or 70 seconds.
Some Apple apps such as Maps, Remote and Timer can override this setting and if a fitness app has an active HealthKit workout activity then the watch will also resume the last activity on wrist raise/face tap. If your app isn't using HealthKit for a workout activity then you have to live with the behaviour the user has selected.
I am seeing an issue with Location Services still being used by my app even if the app has been killed from the multitasking bar. If I go into Settings > Privacy > Location Services I notice that my app has a purple location icon even while there are NO apps in the background. If I turn off Location Services for my app, the icon in the status bar disappears.
I have ensured in my app that I am stopping location services when they are not needed. I have verified this numerous times in Instruments. GPS turns on when it is supposed to and when the task is finished using location services, the GPS is turned off.
In my applicationWillTerminate: delegate, I even set the lcoationManager to nil, set the delegate to nil and make sure all of that is cleaned up. I still see the icon in the statusbar when I KILL my app.
This particular app also has a bluetooth accessory that can make the app do certain things. So for instance, I press a button on my BLE accessory and it makes the app do something which will trigger a UILocalNotification, so I see a banner. I don't know how to reproduce this particular issue, but I've noticed that even if there are NO apps in the multitask bar and I press the button on my BLE accessory, it will trigger the action in the app and I will see the notification banner.
A few questions:
Has anyone else seen anything like this?
How can I ensure that my app is COMPLETELY killed even though I have cleaned up really good on application terminated?
Why would the location services still be running even though the app is killed. Also keeping in mind that I do NOT use any region monitoring or significant location update changes.
Update:
So I took a previous version of the app and reset Location & Privacy settings and to my surprise, backgrounding the app makes the location icon disappear (as it should have been doing all along. To me this means that iOS is keeping some residual information or settings from the app? Anyone have any insight as to what could be going on here?
Update 2:
Still occurs in iOS 8.1.x.