3

I know this can't work because the completion handler is on a background Thread but

where am I supposed do dispatch the main queue or what else do i have to do?

this is the code:

static func isNotificationNotDetermined() -> Bool{

    var isNotDetermined = false

    UNUserNotificationCenter.current().getNotificationSettings { (notificationSettings) in
        switch notificationSettings.authorizationStatus {
        case .notDetermined:
            isNotDetermined = true

        case .authorized:
            isNotDetermined = false

        case .denied:
            isNotDetermined = false

        }
    }

    return isNotDetermined
}
Saurabh Mistry
  • 12,833
  • 5
  • 50
  • 71
  • In your case, the issue is not that's in a background thread, that's okay (you don't do anything with UI), it's the fact that it's "asynchronous". Look for "Async Swift Closure". You'll get often answers about JSON/WebAPICall, but the situation is clearly the same. – Larme Jan 30 '18 at 14:01

2 Answers2

9

You can't do in this way; getNotificationSettings is asynchronous, so you should pass a closure in the method and call right after the switch. Something like this:

static func isNotificationNotDetermined(completion: (Bool) -> Void) {

    UNUserNotificationCenter.current().getNotificationSettings { (notificationSettings) in
        var isNotDetermined = false
        switch notificationSettings.authorizationStatus {
        case .notDetermined:
            isNotDetermined = true

        case .authorized:
            isNotDetermined = false

        case .denied:
            isNotDetermined = false

        }

        // call the completion and pass the result as parameter
        completion(isNotDetermined)
    }

}

Then you will call this method like this:

    YourClass.isNotificationNotDetermined { isNotDetermined in
        // do your stuff
    }
Rico Crescenzio
  • 3,952
  • 1
  • 14
  • 28
4

You can't do that. It's not because completion handler is on a background thread. It's because the function getNotificationSettings() is asynchronous. It returns immediately, before you have your answer.

Imagine that you are cooking dinner, and you ask your daughter "Will your brother be home for dinner?" Your daughter needs to call your son and find out. You won't have the answer to the question as soon as you ask it. You'll have to wait for your daughter to find a phone, make a call, and report back to you.

Async functions are like that. The answer is not known when the function returns. That's what the completion handler is for. It's a block of code that gets executed once the answer has been determined.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 1
    yes, but i cant put the return inside the completion handler, thats the problem. – Some German Developer Jan 30 '18 at 14:06
  • 1
    It's an asynchronous API. Don't fight it. Write your code so that it can react to the status determination **inside** the closure. – Gereon Jan 30 '18 at 14:12
  • What @Gereon said. You cannot write your function to return a true/false answer. It is **not possible.** You need to write your function to take a completion handler that gets executed once the async `getNotificationSettings()` function competes. – Duncan C Jan 30 '18 at 15:39
  • See @RicoCrescenzio's answer. He rewrote your `isNotificationNotDetermined()` function to take a closure, like you should do. (Voted) – Duncan C Jan 30 '18 at 15:42