-1

Been researching this topic, curious if it's possible to schedule a function to run at a specific time same way you can schedule local notifications to trigger at a specific time. Would need this to run even if the app is closed or in the background.

Use Case:

I'm working on an app that that currently sends the user a random message daily "from an array of possible messages" as a local notification. This local notification is triggered at a specific time a user has specified from a datepicker. All of this is working as expected even if the app is closed.

Now I'm trying to figure out a way to show the content of the last random notification received inside the app. I would like to set a labels text to the body.content "random message" of the local notification... but only after they have received the notification. I don't want to show it in the app before it's been delivered. Example: user opens app, sets the local notification time to be received at 3pm. User closes app, notification is received at 3pm, they open the app at 4pm, a label inside the app displays the same message that they received as a notification. Message in app should stay the same till the next day at 3pm since the local notification is set to repeat.

The problem, apparently you can't retrieve the contents of a delivered local notification. Which is why I was wondering if it's possible to schedule a function at a specific time. If so I could then save the generated message as a userdefault value, then trigger a UNTimeIntervalNotification in like 5 seconds and use the same saved value. When the app is opened, I could update the label.text using the saved value. That way, each time they open the app, the label in the app would always be the same as the last notification received.

Im new to swift language, any other suggestions on possible solutions to this problem would be greatly appreciated.

Bowenac
  • 493
  • 8
  • 19
  • 3
    "Would need this to run even if the app is closed or in the background." It doesn't make technical sense. – El Tomato Jan 31 '18 at 03:43
  • 1
    Additionally, you are not even specifying your development platform. – El Tomato Jan 31 '18 at 03:44
  • Updated with more details, not sure how it doesn't make sense, can you explain? Or provide a solution? – Bowenac Jan 31 '18 at 04:12
  • You're going the wrong way about what you're attempting to do. You could determine the message whenever the app is open, schedule the local notification and store the message in UserDefaults or something else. Having the function run on a given time is not necessary. – EmilioPelaez Jan 31 '18 at 15:58
  • @EmilioPelaez how would you suggest using that UserDefaults value only after the notification has been delivered? Otherwise I would be showing the stored message in the app before it's been delivered if they open the app again before the notification was delivered. – Bowenac Jan 31 '18 at 16:03
  • @Moritz removed Xcode tag, thanks. – Bowenac Jan 31 '18 at 16:18

3 Answers3

3

If you want to run code at a specific time, then you should use the Timer class. It is great for executing code repeatedly at a specific time interval, but it's also great for running code at an exact time that you specify.

This is accomplished using a Timer constructor that accepts an Date for when the timer should fire. You can make this date however you want, which is what makes this approach so flexible.

As a simple example, this will create a timer that calls a runCode() method in five seconds:

let date = Date().addingTimeInterval(5)

let timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(runCode), userInfo: nil, repeats: false)

RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
Jaydeep Vora
  • 6,085
  • 1
  • 22
  • 40
YanSym
  • 51
  • 5
  • This is true and is one way of doing this. However the timer will invalidate if the app is suspended (backgrounded). Also you would have limited control in the sense that, you couldn't receive a notification but instead you would have to specify the time beforehand. In many of my own personal cases you don't always know that exact time until the function needs to be called. – Jon_the_developer Jan 31 '18 at 03:43
  • Yes I've read that from this as well https://www.hackingwithswift.com/example-code/system/how-to-run-code-at-a-specific-time However that doesn't work if the app is closed. Updated question with more details. – Bowenac Jan 31 '18 at 04:13
0

You would need to do a list of things, which depends on what you want the function to do. The reason why is because when apps are backgrounded all process are originally suspended until the apps enter the foregrounds again. You can have apps run in the background, but they must follow apples rules (if you don't then your app will not be accepted on the app store). For example, you can play audio while the app is in the background. See this tutorial for an example. Once you have made your app so that it will run in the background then you will need to call the function at a specific time. Using notification would be fine, but really it would be your preference. As for running a function when your app is closed I don't think that your supposed to.

0

You can have a timer fire while in background execution mode.

1) You need to opt into background execution with beginBackgroundTaskWithExpirationHandler.

2) Either create the Timer on the main thread, OR you will need to add it to the mainRunLoop manually with

RunLoop.main.add(timer, forMode: .defaultRunLoopMode)

Note: Something you have to know about Background mode.

  • Apps only get about to 10 minutes (~3 mins as of iOS 7) of background execution - after this the timer will stop firing.
  • As of iOS 7 when the device is locked it will suspend the foreground app almost instantly. The timer will not fire after an iOS 7 app is locked.

Closed State

This doesn't make sense to run timer while app is not active.

Jaydeep Vora
  • 6,085
  • 1
  • 22
  • 40