iOS Run Code Once a Day - ios

The idea behind this app is very simple: download a file. However this app will be for people who are not always within internet access range, so I need it to know that at, say 9:00 AM, to download a file to the hard drive. There will be a button within the app to do it manually as well, but I've already got that working.
As I understand it, this will be difficult if it is even possible. I know that iOS doesn't like multitasking, but I am also aware that it does allow for background timer functions. I am open to any sort of suggestions anyone might have to accomplish this, even if it means writing a separate app. Thanks.
Edit: I see there is the possibility of working with Notifications, or even maybe the Calendar. Ideas in that category as also welcomed.
Edit 2: I also read something about an external server initiating an app, but it gave no description.

Here's the situation regarding background execution and notifications and timers etc. in relation to an app scheduling some activity to happen periodically.
An app cannot execute in the background unless:
It requests extra time from the OS to do so. This is done using beginBackgroundTaskWithExpirationHandler. It is not specified (intentionally) by Apple how long this extra time is, however in practice it is around 10 minutes.
An app has a background mode, the modes are: voip, audio, location, newstand. Even if it has one of these types an app cannot execute without some restrictions. The rest of this discussion assumes the app does not have a background mode.
When an app is suspended it cannot do ANYTHING to rouse itself directly. It cannot previously have scheduled an NSTimer, it cannot make use of something like performSelector:afterDelay. etc.
The ONLY way the app can become active again is if the USER does something to make it active. The user can do this from via of the following:
Launch the app directly from its icon
Launch the app in response to a local notification that was previously scheduled by the app while it was active.
Launch the app in response to a remote notification sent by a server.
A few others: such as URL launching if the app is registered to deal with launching via a url; or if its registered to be capable of dealing with a certain type of content.
If an app is in the foreground when a local/remote notification fires then the app receives it directly.
If the app is not currently in the foreground when a local/remote notification fires then the app DOES NOT receive it. There is no code that is executed when the notification fires!
Only IF the user selects the notification will the app become active and it can execute.
Note that the user can disable notifications, either for the entire device, or just for a specific application, in which case the user will never see them. If the device is turned off when a notification is due to fire then it is lost.

You could use local notifications. They execute code when the user opens the notification that is presented. You can set the local notification to recur at a specified interval (e.g. daily, hourly, weekly, etc). This still requires the user to open the app to get the process started.
UILocalNotification Class Reference
Once the delegate method fires, you only get a few seconds to execute code. Register for a long running background task, and download whatever you need to do. If it can't finish downloading in the 10 minutes you get for the task, then you need to rethink your download strategy.
Apple Multitasking and Backgrounding
We are using this same concept on iOS apps where I work, so this will work if you set it up right.
UPDATE
For those curious how this will work, you just need to implement the UILocalNotification delegate methods. They inherit from the UIApplicationDelegate that should already be in place.
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
// start your long running bg task here and update your file
}
** UPDATE 2 **
Martin H's answer is the most correct so far. But this begs the question, if the user never opens the app, what is the point of downloading data they are never going to see? A recurring local notification reminding them to open the app and update may be the best way, but still requires the user to interact with your app if they want it to remain current and up-to-date.

Background applications have a set time limit (I believe 10 minutes, but don't quote me on that, it could be less) to complete whatever they are working on. You will not be able to use background tasks to do what you want.
What you can do is set an NSUserDefault with the date of the last download. On launch check the date saved, if the date is not the current date, and it is after 9:00am, initiate the download programatically.

I am pretty sure this is not possible, at most what you can do is send push notifications to the user, so that they manually update when required.

Have you tried the following?
if ([[[UIDevice currentDevice] systemVersion] floatValue] >=7.0)
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:600];
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
completionHandler(UIBackgroundFetchResultNewData);
}

Related

iOS - in device settings if i change time it should get notified even in app background, killed state

To get the device settings time change notification, i found that we have to use UIApplication.significantTimeChangeNotification notification and func applicationSignificantTimeChange(_ application: UIApplication) delegate method.
But in my case even though if app in background or in killed state, then i have to show local notification to the user saying that device time is changed. Is it possible, Please let me know if we have any solution for this.
From Apple Document on applicationSignificantTimeChange
If your app is currently suspended, this message is queued until your
app returns to the foreground, at which point it is delivered. If
multiple time changes occur, only the most recent one is delivered.
So, it clearly conveys that this will work only when the app is in Foreground. It is not even queued up when the app is not running.
To display any local notifications when the app is not running, it should be scheduled in the past to trigger it in the future. And it is not possible for the app to know about the time change event when it is not running. It looks like you would not be able to achieve what you have asked.
I don't believe it is. iOS cannot deliver notifications to an app that is not running and they don't get queued up anywhere.
One potential workaround for this however could be to take the current UTC value from a trusted, online source and compare it with what the device thinks UTC is and store that offset. Once your app restarts, calculate this offset again and if it's significantly different from the one you stored previously, take the action you'd take in response to the Significant Time Change notification.

How to execute function and update current state in background even app closed via Swift [duplicate]

The idea behind this app is very simple: download a file. However this app will be for people who are not always within internet access range, so I need it to know that at, say 9:00 AM, to download a file to the hard drive. There will be a button within the app to do it manually as well, but I've already got that working.
As I understand it, this will be difficult if it is even possible. I know that iOS doesn't like multitasking, but I am also aware that it does allow for background timer functions. I am open to any sort of suggestions anyone might have to accomplish this, even if it means writing a separate app. Thanks.
Edit: I see there is the possibility of working with Notifications, or even maybe the Calendar. Ideas in that category as also welcomed.
Edit 2: I also read something about an external server initiating an app, but it gave no description.
Here's the situation regarding background execution and notifications and timers etc. in relation to an app scheduling some activity to happen periodically.
An app cannot execute in the background unless:
It requests extra time from the OS to do so. This is done using beginBackgroundTaskWithExpirationHandler. It is not specified (intentionally) by Apple how long this extra time is, however in practice it is around 10 minutes.
An app has a background mode, the modes are: voip, audio, location, newstand. Even if it has one of these types an app cannot execute without some restrictions. The rest of this discussion assumes the app does not have a background mode.
When an app is suspended it cannot do ANYTHING to rouse itself directly. It cannot previously have scheduled an NSTimer, it cannot make use of something like performSelector:afterDelay. etc.
The ONLY way the app can become active again is if the USER does something to make it active. The user can do this from via of the following:
Launch the app directly from its icon
Launch the app in response to a local notification that was previously scheduled by the app while it was active.
Launch the app in response to a remote notification sent by a server.
A few others: such as URL launching if the app is registered to deal with launching via a url; or if its registered to be capable of dealing with a certain type of content.
If an app is in the foreground when a local/remote notification fires then the app receives it directly.
If the app is not currently in the foreground when a local/remote notification fires then the app DOES NOT receive it. There is no code that is executed when the notification fires!
Only IF the user selects the notification will the app become active and it can execute.
Note that the user can disable notifications, either for the entire device, or just for a specific application, in which case the user will never see them. If the device is turned off when a notification is due to fire then it is lost.
You could use local notifications. They execute code when the user opens the notification that is presented. You can set the local notification to recur at a specified interval (e.g. daily, hourly, weekly, etc). This still requires the user to open the app to get the process started.
UILocalNotification Class Reference
Once the delegate method fires, you only get a few seconds to execute code. Register for a long running background task, and download whatever you need to do. If it can't finish downloading in the 10 minutes you get for the task, then you need to rethink your download strategy.
Apple Multitasking and Backgrounding
We are using this same concept on iOS apps where I work, so this will work if you set it up right.
UPDATE
For those curious how this will work, you just need to implement the UILocalNotification delegate methods. They inherit from the UIApplicationDelegate that should already be in place.
-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
// start your long running bg task here and update your file
}
** UPDATE 2 **
Martin H's answer is the most correct so far. But this begs the question, if the user never opens the app, what is the point of downloading data they are never going to see? A recurring local notification reminding them to open the app and update may be the best way, but still requires the user to interact with your app if they want it to remain current and up-to-date.
Background applications have a set time limit (I believe 10 minutes, but don't quote me on that, it could be less) to complete whatever they are working on. You will not be able to use background tasks to do what you want.
What you can do is set an NSUserDefault with the date of the last download. On launch check the date saved, if the date is not the current date, and it is after 9:00am, initiate the download programatically.
I am pretty sure this is not possible, at most what you can do is send push notifications to the user, so that they manually update when required.
Have you tried the following?
if ([[[UIDevice currentDevice] systemVersion] floatValue] >=7.0)
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:600];
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
completionHandler(UIBackgroundFetchResultNewData);
}

how to start my App in a particular time of the Day in Swift iOS

I have an App built on Swift, I want this App to start every day at some particular time. Logically its like Calendar notification, which gives notification in that particular window whatever we set.
Does is the same scenario is possible with an App in iOS Swift.
What you can probably do is to create a local notification, but this is not opening your app. A local notification is just a way to show a notification on your iPhone and then, if the user taps, it's opening your app.
See more here: https://www.codebeaulieu.com/49/How-to-add-local-notifications-to-your-app
I am not sure what you want to do, you cannot force your application upon the user without the user's consent. What you can do is schedule a local notification so the user knows when to open your app like jomafer proposed already. Also possible is to wake up the app to do stuff in the background:
https://developer.apple.com/library/prerelease/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
For example a silent push notification that will trigger some code, or a scheduled background download.
NONE OF THESE METHODS ARE 100% RELIABLE THOUGH!

iOS Background fetch for local notifications

I have 8 medicine local notifications which differ from day to day.
They work fine for one day but I want to fire them everyday. I used BackgroundFetch to reschedule the local notifications every time fetch is executed. But my problem here is that background fetch depends on how often the user uses the app. What if the user doesn't open the app more often Also I didn't want to implement silent notifications because it will not wake up the app if the user does not have internet connection. what approach should I use instead of background fetch?
EDIT:
I also thought about location updates in background because my notification times are taken from location of user and calculated accordingly. But will this consume a lot of battery?
Since I've got the same issue in an
app that probably does the same stuff as yours, I'd like to share my solution.
It comes with one compromise works only from >=iOS8.
By using an interactive notifications you can reschedule your notifications in background, of course the user need to interact with the notification, but I think that if you different actions instead of open the app or cancel the notification is possible to have more interested user.
It's all about creating a configuration with actions.
Here you can find a tutorial.

How to listen to Calendar events when application in background iOS?

I wrote application for Android that listens on incoming Calendar events and triggers my flow when application in background.
Now I try to do the same for iOS.
I read a lot of stuff and ran some demos that use EKEventStore and background fetch.
However this approach does not satisfy me.
Is there other way to do that?
[EDIT]
Application uses public API only.
Thanks,
The short answer is you can't. Apple will not allow any app to do things like this in the background, as it requires turning the CPU on when it would otherwise be turned off.
When your app is running, you can read all events in the near future (say, two weeks out?) and setup a "local" push notification for the event time.
Also, if the user launches your app fairly often then Apple will allow your app to refresh using Background App Refresh. The device will typically do this in the morning before whatever time the user usually wakes up and turns their phone on for the first time each day, and throughout the day also, based on the user's activity. You can do anything you want during the background app refresh.
Another spanner in the works is how Apple's full disk encryption works. If the phone is locked, there really isn't much your app can do. Most data on the phone is encrypted with the user's passcode. Until the user enters their passcode not much can be done. In this case background app refresh will run as soon as they enter their passcode, but before they launch your app.
Maybe you could have a remote server send push notifications to the phone as well. Not sure if this is an option for you at all or not. Obviously this means the server would need access to the user's calendar data.
In general, the Android model of background execution doesn't apply to iOS.
You can register for calendar events as shown below, but your application will only be notified when it is running. On iOS, that means it is either in the foreground, recently backgrounded and still running, or has been launched/woken up by the system as part of a designated background mode (e.g. background fetch, location updates, VoIP, etc.).
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveEventStoreChangedNotification:)
name:EKEventStoreChangedNotification
object:eventStore];
If your application has a need for one of the designated background modes, you will at least get notifications from time to time (when you are woken up). I've seen approved apps use location updates just to get more execution time, of course YMMV.

Resources