iOS handling initial data sync which may take several minutes - ios

I have an iOS app that needs to sync a lot of data from the cloud to device when first installed, maybe even 2GB worth if the user wants access to everything offline. Without saying "change your design", how can I ensure this initial sync completes without too much interaction from the user?
Currently it will complete as long as they keep my app in the foreground and don't let the device go to sleep. I'd like to allow them to use other apps or let the screen turn off during this process, since it's a pretty boring thing to watch.
I've seen application:performFetchWithCompletionHandler: and
beginBackgroundTaskWithName:expirationHandler, but they only allow for a short amount of time (around 30 seconds) to complete a task. Is there something better, or do I need to complicate my design by stopping my sync every ~25 seconds, and then resume next time I'm given more time by the OS?
My app is like Microsoft Outlook, it has emails (in some case millions), contacts, calendar, and several other areas. I have different sync options to limit the amount of data, but some users want access to everything offline (yes, even emails and attachments that are 10 years old). I think they are silly, but can't argue with the end-users.

I know this is a really old question, but I suggest you use NSURLSession to download data in the background even without your app running.
You simply create an NSURLSession that uses a Background NSURLSessionConfiguration (use NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier:) and create an NSURLSessionDownloadTask for each request you need to download.
NSURLSession will download the data even when your app is not running at all, and it will save the data as files in your app's sandbox. Implement the NSURLSession delegate methods to receive notification of the download completion, read the downloaded files and save them how you see fit.
You should check out Apple's guide on Using NSURLSession.

Related

How to run a large on demand sync on an ios device?

I have been looking at the options available to do a user driven on demand sync of a large data set (roughly 1gb) to a iOS device from a central server. The intention is that the user will go offline some time after the sync is complete, and use the app in offline mode for some time afterwards. However, I am running into a lot of iOS restrictions that seems to prevent this.
The beginBackgroundTask does not allow enough time to complete a sync before its suspended as it only allows up to 30 seconds of background processing. I have seen a few references to this being increased by using audio or gps functions however neither of these are applicable to my situation.
The BGProcessingTask apis are at the systems discretion as to when they are run, so are not sutiable for an on demand process.
The NSURLSession api allows for downloads to occur while the app is suspended, however the problem with this api is that it requires the server to extract all necessary data to a temporary file before it can be downloaded, this process can take several minutes. This introduces the problem where the application can be suspended before the server has completed generating the file to download.
I'm aware a background push can be used to wake the app and start the download using the NSURLSession api if the app has been suspended, however this approach places the execution of the download back at the discretion of the OS which can lead to significant delays in the sync actually starting, which makes for a rather undesirable solution.
Its also worth noting that precalculating and caching the data to download in advance is not a viable option due to the number of updates that occur and different permutations of data depending on permissions assigned to each user.
With that, are there any apis that I have not considered, or any misinterpretations to the ones above that would allow me to achieve an on demand sync of such a large data set?
It seems iOS is missing the ability for a user to explicitly opt in to starting a long running process and allow it to continue till complete. I'd assume some other enterprise apps would have come across a similar problem before, and I would be gratefull to see how its been solved.

Periodic background synchronization

Im quite new to iOS programming and now want to implement a periodic background synchronization to synchronize my server data with client data. What I want to achieve is comparable with Androids SyncAdapter where you can define a time interval (for example each 30 minutes) and the system will trigger the defined task automatically in the background.
Until now I could not find such mechanism for Swift 3.0 so I need to ask if somone has experience or some hints for me how I can achieve this.
What I want to do sounds quite simple:
When the app starts for the first time the app should setup a sync manager which automatically triggers a background task every 30 minutes. The background task is responsible to synchronize server and client data (using Alamofire).
How can I do that?
There is an iOS feature called BackgroundFetch, which you can set up for
regularly downloads and processes small amounts of content from the network
You can setup a minimumBackgroundFetchInterval.
In contrast to the mentioned Android feature, this interval is not guaranteed though.
The OS does some heuristic in a blackbox. It rewards you for using a "reasonable" (to the OS) CPU time/ power consumption and also for being used often by the user. On the other hand you get punished for draining the battery or (even worse) never being used/opened by the user.
See: Apple Sample and Apple Docs
Update: Since iOS13, BackgroundFetchis deprecated.
There is a similar, new API named BGTask, BGAppRefreshTask is the equivalent to deprecated BackgroundFetch.
See Apple Docs
Alternatively, depending on your needs, you can post a Silent (push) Notification whenever the users data changes on server side. A silent push wakes up your app without notifying the user, so you can fetch data and maybe inform the user by scheduling a local notification.
See: Apple Documentation
You can't. Apple doesn't allow 3rd party apps to have regular background time like that. You'll need to come up with another approach like implementing a silent push notification from your server when new content is available.
As #ekscrypto points out in their comment, you can use Background fetch to load small amounts of data when the system decides to fetch it. However, you don't have any control over when that fetching takes place. Search on "Fetching Small Amounts of Content Opportunistically" in the Xcode help system for more information.

how to handle a long wait time for data, when ios 8+ app has been backgrounded by user

I've spent a lot of time looking at the options but am still not 100% clear, so wanted to reach out for some guidance.
Scenario is this:
User submits an HTTPS request to our backend server for some data via an iOS app
Depending on the data, the first (only) request can take a REALLY long time. like, say, 10+ minutes (shocking i know)
When that payload finally does become available and is returned via the HTTPS request, we then want to use it to update the UI in background.
The assumption here is that the user has moved on to another app whilst waiting for the data to arrive (and lets also assume they haven't killed the app).
Is it possible to handle this via iOS 8+ API's without the app being force/killed by Apple when in the background ?
Could we use background task for example?
var backgroundTask: UIBackgroundTaskIdentifier
xxx.beginBackgroundTaskWithName...
etc
Before testing some code blocks we just wanted to see if someone has (a) already done this and/or (b) whether we're heading in the right direction
Thanks for your help.
You should re-think on your web service which may take almost 10 min to process. If you are not able to optimize server task processing time then below one of the idea may be help you.
You can divided your one request into multiple request to reduce processing time and get response in faster way.
Your server should sent notification to app when its done with its task. So app will came to know task is done.
I am not sure why you try to update UI when apps in background mode , you may try to update UI when users come to foreground mode from background mode.
Please check this link which show as example of long running task. Where its use a blank audio play to keep alive app background task.
You can used "Background fetch" functionality.
For learning purpose you can refer this link

Does NSUrlSession Prevent the Application from suspending?

I have an app that send 300+ files across the network, normally we request an additional 10 minutes timer when the app moves to the background in case we need to send, but after 10 minutes the app is moved to the suspended state.
Can NSUrlConnection prevent this suspension and continue download from the background>
you get only 3 minutes in iOS 7, not 10 as before.
NSURLConnection cannot help you there.
NSURLSession has a facility for uploading files in the background, outside of that time. However, it doesn't keep a continuous task running like UIBackgroundTaskIdentifier-based methods, and you must use on-device files as the basis of the upload. I found it to take a lot of work to get it right, so be prepared. I'd start with a thorough review of Apple's URL Loading System Programming Guide, which isn't really well written, but is entirely necessary.

ASINetworkQueue Correct Usage and Storage

I have an app that submits data using ASIFormDataRequest to a remote web site. I want to allow the user to store them for upload later if they are offline (eg: iPod touch or out of cell coverage, etc). Is ASINetworkQueue the appropriate tool to use? I imagine I would store the request in a queue belonging to the app delegate and, whenever a new submission was added or the app launched, reachability would be tested and, if good, would complete each request in the queue.
Is that logic correct? (I know it is bad practice to check reachability immediately on app launch, but I would tweak that to a good time.)
If so, my next question is, how do I get a ASINetworkQueue to persist between launches, both cold and from background? I imagine it would involve writing it to NSData and writing that to NSUserDefaults or even to file.
Thanks for any help!
If you are going to upload data asynchronously but handle offline usage, I would recommend writing the data to a local database or file and then having some sort of "uploaded at" timestamp for a status. When your app starts up you can query your local database for any objects that have not been uploaded. I don't know what your app is doing but you may find this method less error prone and better for giving proper feedback to your user through the UI.

Resources