1

When user launch the app or finish editing the data I need to update local notifications, basically it takes around 2-3 seconds in async way. I need to make sure that this code executes even if app leave foreground. What I have now:

func buildLocalNotifications()
    let dq = DispatchQueue.global(qos: .userInteractive)
    dq.async {
       //recreate the notifications
    }
}

And I can call this method from didFinishLaunchingWithOptions or when user save the form and everything works like a charm while app stays active for more then 3-4 seconds and its not blocking UI of course.. but if user lock the screen or terminate the app - this code won;t finished and notifications won't be created. How to safely execute sensitive code? What is coming on my mind - show up a loader while performing this action - but it will block the user interaction

Igor Lantushenko
  • 1,771
  • 10
  • 19

3 Answers3

2

Ok I found the solution for the task which requires some time and should not be interrupted when app leaves foreground. So we need beginBackgroundTask and endBackgroundTask

Small manager which you can use to execute code even when app is not in foreground

class BackgroundTaskManager {
    let backgroundDQ = DispatchQueue.global(qos: .background)
    var backgroundUpdateTask: UIBackgroundTaskIdentifier!

    init(withName: String) {

        self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(withName: withName) {}
    }

    /* Using completion handler to know when code is done*/
    func runBackgroundTask(withCode: @escaping (_ cH: @escaping () -> Void) -> Void)
    {
        backgroundDQ.async {
            withCode() {
                self.endBackgroungTask()
            }
        }
    }

    func endBackgroungTask() {
        if backgroundUpdateTask != nil && backgroundUpdateTask != UIBackgroundTaskInvalid {
            UIApplication.shared.endBackgroundTask(backgroundUpdateTask)
            backgroundUpdateTask = UIBackgroundTaskInvalid
        }
    }    
}

And you can use it like

let taskManager = BackgroundTaskManager(withName: "LocalNotifications")
taskManager.doBackgroundTask() { (cH) in
    //Your code goes here
    //Send back completion handler so system knows when to finish background task
    cH()
}

More information you can find on the Medium

Igor Lantushenko
  • 1,771
  • 10
  • 19
0

If you want to make sure your code gets executed even if the user closes your app, you need to call your function in applicationWillTerminate. However, you only have ~5 seconds to execute code, before the system closes your app, so asynchronous execution is not encouraged here. It also doesn't matter if you execute code synchronously, since the user already quit your app, so you won't be blocking any UI updates.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • first of all thank you, will try approach with `applicationWillTerminate`. And also question: f.e. I started updating notifications after saving some forms and its almost done but then user terminated the app and updating starts from `applicationWillTerminate` - what about the first execution? will it be stopped before `applicationWillTerminate`? – Igor Lantushenko Jun 12 '17 at 09:39
  • You should test it to be sure, but I am not sure if the system closes your processes before calling applicationWillTerminate or if it continues running them while your code is executed in applicationWillTerminate. But you can cancel work items added to a DispatchQueue manually, see [this](https://stackoverflow.com/a/38372384/4667835) answer. – Dávid Pásztor Jun 12 '17 at 12:05
-2

Try to excute your code in background

 DispatchQueue.global(qos: .background).async {
      // your code here 
    }
Muhammed
  • 584
  • 1
  • 11
  • 24
  • 1
    thanks @Muhammed tried just now to use `. background ` instead of `. userInteractive` and noticed that when I lock device - it also stops, but when unlock - continues, so looks like my solution will be with `applicationWillTerminate ` or `applicationDidEnterBackground` or `applicationWillResignActive` – Igor Lantushenko Jun 12 '17 at 11:11
  • No problem @IgorLantushenko after it work add your solution as an answer :) – Muhammed Jun 12 '17 at 11:19