Mason Ticehurst
Mason Ticehurst

Reputation: 474

iOS - aSyncAfter while app is in background

I'm attempting to run a a simple iOS application that pushes a notification to a user's screen after a specified time.

So far, this is what I have (borrowed from another thread):

DispatchQueue.global(qos: .background).async {
     print( "background task" )

     DispatchQueue.main.asyncAfter( deadline: .now() + milliseconds( 2000 )) {
       let content = UNMutableNotificationContent()
       content.body = "Testing :)"
       content.badge = 1

       let trigger = UNTimeIntervalNotificationTrigger( timeInterval: 2, repeats: false )
       let request = UNNotificationRequest( identifier: "test", content: content, trigger: trigger )

       UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)

       print( "background finish" )
     }
}

My only issue is that the aSync After doesn't run whenever the app is in the background.

For example, if a user goes into their lockscreen or a different app, the notification never gets triggered.

Would anyone have a suggestion for how I could achieve this?

Thank you! :)

Upvotes: 2

Views: 1194

Answers (1)

user1046037
user1046037

Reputation: 17695

Approach:

  • Use UNNotificationRequest with time interval
  • Below mentioned solution would work in the following scenarios:
    • Foreground
    • Background
    • App is closed

Steps:

  1. Set the delegate (to be alerted in foreground)
  2. Request authorisation from user to be alerted
  3. Create the notification
  4. Add it to the notification center

AppDelegate:

AppDelegate must conform to UNUserNotificationCenterDelegate.

Set the notification center's delegate to the AppDelegate

import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        UNUserNotificationCenter.current().delegate = self

        return true
    }

    //MARK: UNUserNotificationCenterDelegate

    //This is required to be alerted when app is in foreground
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        print("will present")
        completionHandler([.alert, .badge, .sound])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                didReceive response: UNNotificationResponse,
                                withCompletionHandler completionHandler: @escaping () -> Void) {
        print("did receive")
    }
}

Setting up notification:

import UserNotifications

private func setupNotification() {

    requestAuthorization { [weak self] isGranted, error in

        if let error = error {

            print("Request Authorization Error: \(error)")
            return
        }

        guard isGranted else {
            print("Authorization Denied")
            return
        }

        self?.addNotification()
    }
}

private func requestAuthorization(completionBlock: @escaping (Bool, Error?) -> ()) {

    let center = UNUserNotificationCenter.current()

    center.requestAuthorization(options: [.alert, .badge, .sound]) { isGranted, error in

        completionBlock(isGranted, error)
    }
}


private func addNotification() {

    let content = UNMutableNotificationContent()

    content.title = "Testing Notification"
    content.body = "This is a test for notifications"
    content.sound = .default()

    let timeInterval = TimeInterval(5)
    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeInterval, repeats: false)

    let request = UNNotificationRequest(identifier: "Something",
                                        content: content,
                                        trigger: trigger)


    let center = UNUserNotificationCenter.current()

    center.add(request) { error in

        if let error = error {
            print("Error adding notification request: \(error)")
        }
        else {
            print("Successfully added notification request")
        }
    }
}

Upvotes: 2

Related Questions