I'd like to get UIApplication.shared.applicationState from a background thread. If I try to get the application state from a background thread, I get errors when accessing it since it's not the main thread (since it's a UIKit API).
The reason I'm doing this is so I can log events that also includes information such as the current application state. Logging events for me is happening in the background so it does not lock up the main thread.
Is there an alternative for getting the application state within a background thread?
Setup notifications for changes to the state on the main thread and assign them atomically to a variable. That variable can now be accessed atomically as well from your background thread.
Related
In my ios app, I start listening user's location updates in the background for a while (up to 15 mins) when I receive background fetch execution. However, after I stop updates, the app crashes with the 0x8badf00d error.
I've enabled background location and background fetch permissions, and I also have enabled background location updates on CLLocationManager.
Any idea on why this error happens?
The problem isn’t that it isn’t running in the background, but rather whatever was running was blocking the main thread.
The 0x8badf00d (“ate bad food”; lol) indicates that the watchdog process (that monitors for dead/blocked processes) killed your app, generally because you did something to block the main thread. If you avoid blocking the main thread, this error should go away. See Technical Note 2151: Understanding and Analyzing Application Crash Reports and search for 0x8badf00d.
As it says:
The exception code 0x8badf00d indicates that an application has been terminated by iOS because a watchdog timeout occurred. The application took too long to launch, terminate, or respond to system events. One common cause of this is doing synchronous networking on the main thread. Whatever operation is on Thread 0 needs to be moved to a background thread, or processed differently, so that it does not block the main thread.
They’re focusing on synchronous network requests, but it can be anything that blocked the main thread for too long, whether a slow synchronous process or a deadlock or whatever. You should look at the stack trace for thread 0 and see if you can identify what blocked the main thread. There’s not enough here for us to diagnose it, though.
Common culprits include synchronous network calls, synchronous GCD calls, inappropriate use of semaphores, locks, or dispatch group “wait” calls, deadlocks, etc.
I was trying to open a URL session for a chunked response, I am able to achieve this by setting backgroundSessionConfigurationWithIdentifier in NSURLSessionConfiguration object. The URL session still runs if app goes to background, but the session terminates once I quit the app by swapping out from multitask view. Is there a way to restrict quitting the app till didFinishDownloadingToURL delegate called.
I have achieved the similar functionality in my android app using a native thread (boost thread reside in a .so called by UI thru JNI) which does not terminate if the UI is swapped out from the multi task view. Is there a way to achieve same in IOS app?
regards,
Birajendu
According to NSURLSession guide background session task executes in different process (not thread). And finished even if initiator app was killed. You can reassign to bg task when relaunch app.
In both iOS and OS X, when the user relaunches your app, your app should immediately create background configuration objects with the same identifiers as any sessions that had outstanding tasks when your app was last running, then create a session for each of those configuration objects. These new sessions are similarly automatically reassociated with ongoing background activity.
Not sure is it possible to get the task result if your app was terminate during bg session and session completed before you restart app.
I have an instance of AVAudioRecorder and I have noticed that when the user closes the app too fast with a larger recording the file does not get saved properly.
This even happens when I call [recorderObject stop] in the main thread and the file gets saved locally.
I have also tried moving the file after the recording has stopped (in the (void)audioRecorderDidFinishRecording:successfully: method). But I have noticed that when I do the move with NSFileManager in a background thread with high priority, it too doesn't always finish.
Is there a way for me to insure that the files get saved, even if the user exits the app shortly after finishing a longer recording?
Thanks
Review Apple's documentation for executing tasks in the background.
Apps moving to the background are expected to put themselves into a
quiescent state as quickly as possible so that they can be suspended
by the system. If your app is in the middle of a task and needs a
little extra time to complete that task, it can call the
beginBackgroundTaskWithName:expirationHandler: or
beginBackgroundTaskWithExpirationHandler: method of the UIApplication
object to request some additional execution time. Calling either of
these methods delays the suspension of your app temporarily, giving it
a little extra time to finish its work. Upon completion of that work,
your app must call the endBackgroundTask: method to let the system
know that it is finished and can be suspended.
I am fetching items asynchronously using blocks from different sources like …
EKEvents Reminders
Remote JSON feed using NSURLSession
… also I am fetching EKEvents calendar events in the classic synchronous way.
After the data fetching for each source is finished I post a notification and immediately add respective items as subviews.
The problem: Items/views only get displayed after a delay of a couple of seconds, sometimes even longer (long after getting the actual result response). This is not the case for the synchronously fetched items like for calendar events – they show up immediately.
(Curiously using the new Xcode6 live view debugger I can see the new item views there but not in the actual simulator or device.)
Could this have something to do with async fetches not happening on the main queue?
Is there anyway to change this async behaviour have all results show up as generated views immediately?
When you post the notification, are you dispatching that to the main queue? If not, does your handler dispatch the UI updates to the main queue?
When you post a notification from a background thread, the handler is called on a background thread. Thus, if you try to do UI updates in response to a notification sent from a background thread without dispatching the UI updates back to the main queue, you'll see the sort of behavior you describe.
Is applicationDidEnterBackground ALWAYS called before applicationWillTerminate in an iOS app? I know that applicationWillTerminate is not always called (multitasking) - but when it is called, is applicationDidEnterBackground ALWAYS called first? I don't want to duplicate code unnecessarily by including it in applicationWillTerminate if it is already included in applicationDidEnterBackground, for an app that supports multitasking.
in ios 4.0 and later applicationDidEnterBackground is called instead of applicationWillTerminate so you don't have to call both of them. Here is the portion of the Apple docs:
Discussion
In iOS 4.0 and later, this method is called instead of the
applicationWillTerminate: method when the user quits an application
that supports background execution. You should use this method to
release shared resources, save user data, invalidate timers, and store
enough application state information to restore your application to
its current state in case it is terminated later. You should also
disable updates to your application’s user interface and avoid using
some types of shared system resources (such as the user’s contacts
database). It is also imperative that you avoid using OpenGL ES in the
background.
Your implementation of this method has approximately five seconds to
perform any tasks and return. If you need additional time to perform
any final tasks, you can request additional execution time from the
system by calling beginBackgroundTaskWithExpirationHandler:. In
practice, you should return from applicationDidEnterBackground: as
quickly as possible. If the method does not return before time runs
out your application is terminated and purged from memory.
You should perform any tasks relating to adjusting your user interface
before this method exits but other tasks (such as saving state) should
be moved to a concurrent dispatch queue or secondary thread as needed.
Because it's likely any background tasks you start in
applicationDidEnterBackground: will not run until after that method
exits, you should request additional background execution time before
starting those tasks. In other words, first call
beginBackgroundTaskWithExpirationHandler: and then run the task on a
dispatch queue or secondary thread.
The application also posts a
UIApplicationDidEnterBackgroundNotification notification around the
same time it calls this method to give interested objects a chance to
respond to the transition.
For more information about how to transition gracefully to the
background, and for information about how to start background tasks at
quit time, see iOS App Programming Guide.
Hope this helps clear the issue for you man.
Adrian
Here is the link to the technical note that is available on developer section. It is dealing with networking and multitasking. The actual method used in this doc deals with only applicationDidEnterBackground and since iOS 5 they have a system called watchdog which terminates the app if the network is unresponsive automatically. Hence there is no need to actually call applicationWillTerminate and try to execute codes to allow your app to finish its task before the app is terminated. The app will enter the background and will continue its task until the last task is completed. I hope that makes sense, but here is the link. Please read the watchdog section.
https://developer.apple.com/library/ios/#technotes/tn2277/_index.html#//apple_ref/doc/uid/DTS40010841
Hope this helps. :)