Using background fetch to send data to server? - ios

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)

Related

Fetching data in a background and sending notification in iOS

What I want to do is: when my app is running in the background, I want to fetch data from API, every, let's say, 5 minutes. If some data changed I want to send a notification to the user. Is something like that possible in Swift? My problem is that I don't know how to run code in the background. I looked up background fetch but it looks like it was not made for this purpose (I can't be sure it will be fired after x amount of time with this). My app will be mostly user opening it once, setting some settings and then leave it in the background for notifications and never open it again. Any suggestions on what I can use for this purpose? I'd like to avoid creating a backend that will send data to the app, if possible.

Where and When to get data for Watch Complication

After working with complications for a few days, I feel confident saying the following about the update process for updates that happen at a prescribed interval:
The system calls requestedUpdateDidBegin()
This is where you can determine if your data has changed. If it hasn't, your app doesn't have to do anything. If your data has changed, you need to call either:
reloadTimelineForComplication if all your data needs to be reset.
extendTimelineForComplication if you only need to add new items to the end of the complication timeline.
Note: the system may actually call requestedUpdateBudgetExhausted() instead of requestedUpdateDidBegin() if you've spent too much of your complication's time budget for the day. This is the reason for this question.
If you called reloadTimelineForComplication, the system will call getCurrentTimelineEntryForComplication (along with the future and past variants that get arrays, depending on your time travel settings)
This is conjecture as I haven't tested it yet, but I believe if you called extendTimelineForComplication that only the getTimelineEntriesForComplication(... afterDate date: NSDate ...) would be called.
The system will then call getNextRequestedUpdateDateWithHandler so you can specify how long until your complication requires a new update.
Apple's documentation is quite clear that you should not ask for updates too often, or conduct too much processing in the complication code or you will exhaust your time budget and your complication will stop updating. So, my question is: where and when do you do the update?
For context, my scenario is a URL with return data that changes up to two times per hour.
The most obvious place in which to put the URL fetch code is func requestedUpdateDidBegin() Fetch the data, store it, and if there's no change, just return. If there was a change then extend or reload the timeline.
However, a URL fetch can be costly. Alternatives:
Put the code on the phone app and send it over with a WCSession, but if the user closes that app then the updates will no longer happen.
Use push updates, but this isn't a web app, so I have no place to send them from.
Obviously I will update all the data when the user interacts with the watch app, but that now means it only gets updated when the user uses the app, which negates the need for a complication.
Is there anywhere else? Can I have a periodic function in the watch app that isn't part of the complication? Where is the right place to fetch the data for a complication update?
For watchOS 3, Apple recommends that you switch from using the complication datasource getNextRequestedUpdateDate scheduled update to update your complication.
The old way for watchOS 2
requestedUpdateDidBegin() is really only designed to update the complication. Keeping your complication (and watch app) up to date usually involves far more than reloading the timeline (and asynchronously retrieving data never fit in well with the old approach).
The new way for watchOS 3
The new and better approach is to use background refresh app tasks. You can use a series of background tasks to schedule and handle your app extension being woken in the background to:
Fetch new data
using WKWatchConnectivityRefreshBackgroundTask to obtain data from the phone, or
using WKURLSessionRefreshBackgroundTask to download data from a server
update your model once the data arrives,
update your complication from the model (by reloading or extending the timeline), and finally
update your app's dock snapshot to show the data on the dock
Call each tasks’s setTaskCompleted method as soon as the task is complete.
Other benefits of using app tasks
One of the key features about this design is that the watch extension can now handle a variety of foreground and background scenarios which cover:
initially loading data when your app/complication starts,
updating data in the background, when the extension is woken by a background task, and
updating data in the foreground, when the user resumes your app from the dock.
Apple recommends that you use each opportunity you are given regardless of whether your app is in the foreground or background to keep your complication, app, and dock snapshot up to date.
Are there any limitations?
The number of total available tasks per day is divided among the number of apps in the dock. The fewer apps in the dock, the more tasks your app could utilize. The more apps in the dock, the fewer you can utilize.
If your complication is active, your app can be woken up at least four times an hour.
If your complication is not active, your app is guaranteed to be woken at least once an hour.
Since your app is now running in the background, you're expected to efficiently and quickly complete your background tasks.
Background tasks are limited by the amount of CPU time and CPU usage allowed them. If you exceed the CPU time (or use more than 10% of the CPU while in the background), the system will terminate your app (resulting in a crash).
For more information
A good introduction explaining when and why to update your watch app is covered in Designing Great Apple Watch Experiences.
For specifics, the Keeping Your Watch App Up to Date session covers everything you need to know to keep your complication, app, and dock snapshot up to date.
WatchBackgroundRefresh sample code demonstrates how to use WKRefreshBackgroundTask to update WatchKit apps in the background.
Edit: El Tea (op) has posted a good answer at https://stackoverflow.com/a/32994055/630614
This is an interesting question/problem, and I've been wondering about a lot of the same!
For the most part, it seems that when I'm working on a new complication I need to step back and see when I really want to update it. A "countdown" complication could set all future timeline entries at one time, when the "end date" is set. An app that shows the current status of a web service could have relevant data stored in NSUserDefaults when an APNS comes through.
If you don't have access to APNS, don't want to run your iOS app in a background mode, and don't want to make HTTP requests from Apple Watch, I can think of 2 other options.
1) Schedule local notifications. The good part is that your Apple Watch should run didReceiveLocalNotification, but the bad part is that the user will get a notification when you're simply trying to check the status without a disruption.
2) Send a message to iOS via sendMessage(_:replyHandler:errorHandler:) in your reloadTimelineForComplication method, setting nil for the replyHandler to make it as quick as possible:
Calling this method from your WatchKit extension while it is active and running wakes up the corresponding iOS app in the background and makes it reachable.
Your iOS app could perform whatever network requests are needed and then store the information or push it to Apple Watch. Unfortunately, I don't think the watch extension will have it's session.didReceive... called until you run it, but you could access the data on the next call to requestedUpdateDidBegin.
As I said, I'm very interested in this same thing, so post some thoughts back and maybe we can extrapolate on some best practices here.

How to poll an API safely and efficiently?

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.

Manage iPhone app both offline and online

I am stuck to a point, I am managing my app offline also.. first time i get all data (images) from a webservices and store its path into sqlite, now I take an int value 0 or 1 and store its state into NSUserDefaults now I am facing problem in updating those images, like if images are changed how should I notify into my app, I searched it on Google and only solution is to send push notification to app when record is updated. What if user do not allow push notification?
Is there any other solution to manage app offline and update only when record is changed from online database?
You can sync your Data with server Periodically , like call a webservice which check if images have been changed then fetch the new images and if images are not changed then continue with old data.You can add a Boolean Value on server end which can tell you if data on server is updated or not or you can check this with Time stamp like when data is updated last time then compare your local time with Server time at which data has been updated . Good Luck !!
There are ways to handle such kind of situation:
Use push notifications which is the best solution for such situation.
Query the server periodically by giving the ability to the user to set the time interval from app settings.
Query the server whenever the app came from background to foreground.
An idea is to use BackgroundFetch to update the app content while it is not running. I am using similar fetch for one of my apps where I update the content before the user opens the app. I am fetching a small list of items that is indicating which one is up to date and which is not. Then, at runtime I present an option to the user to manually update these items, but of course you can also download all that while in backgroundfetch. My app is without network reach most of the time, and backgroundFetch will update the items list first thing when there is some internet connection.
There are two important methods here that you need to register, setMinimumBackgroundFetchInterval: and application:performFetchWithCompletionHandler: . You can read more about them in Apples guides for background modes.
You can also check out this good tutorial about this fetching capability: http://www.appcoda.com/ios7-background-fetch-programming/
There is way which has being most popular as most of peoples are preferring
At server side build mechanism, which can send lists of images updated after particular date/time.
To keep track of last sync date/time at locally.
Pinged on server with last date/time in case of first time pass any past date and check for update, if there is then download updated images, Otherwise.
Now you have to decide this process when would be query to server
1) At every first time application will be load. (At didFinishLaunchingWithOptions).
2) Query the server periodically by giving the ability to the user to set the time interval from app settings or else where would be preferable.
3) Query the server whenever the app came from background to foreground.

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.

Resources