How to poll an API safely and efficiently? - ios

I'm developing an enterprise iOS app in Swift that needs to pull a list of items from our API and display them in a table view.
The list may change a few times a day but our system won't notify us when the data changes.
Instead, the app will need to poll regularly, say every two hours, to get the latest data and refresh the list. I have implemented the API call using NSURLSession directly.
My question is, what is a safe and efficient way to set up a polling mechanism? What if there are additional API services that must be polled, perhaps on different intervals?

Since you are developing an enterprise app and don't need app store approval you can 'misuse' one of the existing background modes, such as VoIP to periodically poll your data.
My suggestion, however, is to implement some code on another server that can poll the API and send a push notification to the devices when there is new data. This will be simpler to implement in the iOS app and more efficient in terms of battery life and data traffic. It also won't require the user to restart your app after device resets.
You can also easily use the same server to check additional data sources in the future.

An efficient polling mechanism can be implemented via NSTimer(s).
You can have multiple NSTimers fetching data from different locations and working on different dispatch queues.
Then, when you fetch new data, you can broadcast a local notification with the new objects (which is similar to Core Data model).
Your app would be able to access the retrieved data from anywhere.
If you only need to use the data in one location, you could use a delegate or a block-ish callback model.

Related

Using background fetch to send data to server?

I want to send updates to a database from the background every now and then with an app that I am building (for HealthKit things like user's steps taken, heart rate, etc.). I believe I can do this using background fetch. However, from everything I have read on background fetch, it seems like it is mainly just used to grab data for the app so it can display correctly when the user opens it next. Is it reasonable (or recommended) to use background fetch to send data to a database? Thanks.
Depends on what you want to send.
Location services for example have their own background capability with events that you should listen on. In their delegate methods you can send that data to your API.
Background fetch is as the name says rather used for randomly receiving custom data while the app is in background. There is no fixed schedule when the callback gets called. So you might actually either send the same data many times because they did not get updated, or not enough times that you miss some updates (unless you keep them in a database locally)

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.

Daily background task in iOS

I'm building an app that fetches data from a third party server and syncs some of that data to my own server. The data for all users will be aggregated on my server and the results will be displayed in the app. The whole data sync (3rd party server -> App -> My server) should be done at least once a day. The app is only for a limited group of users and will be distributed with an enterprise account.
I'd prefer it to sync the data in the background, so the results on my server are always up to date and do not depend on the single users to open the app. I figured I'd use setMinimumBackgroundFetchInterval with UIApplicationBackgroundFetchIntervalMinimum so the sync would be handled in performFetchWithCompletionHandler in my AppDelegate. Unfortunately it doesn't seem to be possible to set a fixed interval for the background fetch. So I can't control when the sync is done, since it partly depends on the way the app is used when and how often the background fetch is executed.
Is there a way to modify the background fetch so I could guarantee the daily sync?
Or is there any other way to execute a background task on a daily basis with which I could accomplish the above?
The only solution I could come up with is a usability nightmare with daily local notifications to remind the users to open up the app, so that the background fetch can "learn" when to execute. I know this sounds bad, but I do have to present a solution to our customer :/

Receive update from web server to iOS App and synchronize data

i'm writing an app that manage a sqlite database, and i have write a web server, i want the user register in my web server with username and password, i already know how make a request from ios app to server and receive the response, but i want enable also the synchronization of the sqlite database to other device, i now that with core data i can use iCloud synchronization, but for now i prefer use sqlite, and find a way to synchronize it, for example i want create this:
make a change in the sqlite in the iPhone app;
the app send this change to the server for that user;
then the server have to send this update to other device connected at that user;
and now i can't go over, how the server can send this change to the other device? the device has to be always listen to the server? or there is a way to send this update directly to some device and handle it? like an apple push notification?
EDIT: if it's possible use an apple push notification to do this, i doesn't want alert with text sound and badge the user, but send a "silent notification" it's possible?
As a high-level there are a few different ways to approach this, all of which have pros and cons. Two name two examples you can do a polling method, active push or a hybrid approach.
Polling: at some pre-determined interval the app tries to "phone home" and send the delta db changes up to the server. Here you know that your server will be expecting X number of responses in any given interval so you can appropriately gauge your load.
Active Push: The user decides when they want those changes to be transmitted to the server by hitting a "Sync" button. This allows the user to only push data back up to the server when they know there's a change but an over zealous user may make a change, upload, make a change, upload, etc instead of queueing up a bunch of changes and sending them all at once. This may create frequently unneeded server calls.
Hybrid: You setup a polling schedule within the app AND give the user the ability to Sync at-will in the event there is a critical change that needs to be made ASAP.
Regarding the listener side of the equation you face a similar challenge conceptually. If the original user makes 20 changes and presses Sync 20 times do you bombard the second user's device 20 times as well or do you queue those changes up and send them down every 5 minutes (as an example)? Unless you have both devices paired to each other or are connected to the same network AND visible to each other via your app you're going to need to leverage that back-end server. Push notifications can be very useful in this manner but there is extra development and setup overhead to take into account to properly implement them.
To boil this all down I would recommend laying out what YOU want your syncing model to look like before you start marching down a path.

iPhone multitasking and webservice calls

Within my iPhone application I periodically make calls to a webservice, providing the endpoint with a list of numeric IDs. The webservice then returns information relating to the IDs it receives.
This is all well and good. However, I would like to be able to provide functionality whereby the user will receive a local/push notification when these changes occur, regardless of whether the application is open or not.
I'm just looking for guidance on my options in this scenario. As I see it, there are two main approaches: calculate any data changes on my webserver and send a push notification to all devices, or query the webservice from the device itself.
The second option seems ideal, as not all devices will need each push notification, but I'm unsure as to whether this is possible with the current state of iOS' multitasking APIs. Any advice would be appreciated.
Bad news: it's not possible. Apps can only run in the background for a short period of time after the user has exited unless it fits into a small number of categories (GPS, VoIP, etc).
Web services, unfortunately, do not count. So this would have to be performed on the server side and with push notifications.

Resources