Return UNAuthorizationStatus in func

Hi Everybody,


I am trying to implement a function that returns the current UNAuthorizationStatus for use in a View to show a button or not. The function below doesn´t work because the closure is executed after the return - is there any simple way to achieve this?


func getStatus() -> UNAuthorizationStatus {

        var result: UNAuthorizationStatus = .notDetermined

        UNUserNotificationCenter.current().getNotificationSettings(
            completionHandler: { (settings) in
                result = settings.authorizationStatus
                print("result in closure = \(result.rawValue)")
            }
        )
       
        print("result at return = \(result.rawValue)")
        return result
    }


Sorry, if this is a bit of a rookie question but I don´t seem to be able to figure this out.


Thanks

Florian

Accepted Reply

A simple advise, never try to return a value from asynchronous call.


Completion handler pattern is one of the preferred way in UIKit apps:

func getStatus(completion: @escaping (UNAuthorizationStatus)->Void) {
    UNUserNotificationCenter.current().getNotificationSettings(
        completionHandler: { (settings) in
            let result = settings.authorizationStatus
            print("result in closure = \(result.rawValue)")
            completion(result)
    })
}


But, if you are using SwiftUI, you should better use some Combine featrures, an example using Future:

func getStatus() -> Future<UNAuthorizationStatus, Never> {
    return Future {promise in
        UNUserNotificationCenter.current().getNotificationSettings(
            completionHandler: { (settings) in
                let result = settings.authorizationStatus
                print("result in closure = \(result.rawValue)")
                promise(.success(result))
        })
    }
}


Anyway, which would best fit for your app depends on how and where your app calls this method. Please show more code how you want to use this method.

Replies

A simple advise, never try to return a value from asynchronous call.


Completion handler pattern is one of the preferred way in UIKit apps:

func getStatus(completion: @escaping (UNAuthorizationStatus)->Void) {
    UNUserNotificationCenter.current().getNotificationSettings(
        completionHandler: { (settings) in
            let result = settings.authorizationStatus
            print("result in closure = \(result.rawValue)")
            completion(result)
    })
}


But, if you are using SwiftUI, you should better use some Combine featrures, an example using Future:

func getStatus() -> Future<UNAuthorizationStatus, Never> {
    return Future {promise in
        UNUserNotificationCenter.current().getNotificationSettings(
            completionHandler: { (settings) in
                let result = settings.authorizationStatus
                print("result in closure = \(result.rawValue)")
                promise(.success(result))
        })
    }
}


Anyway, which would best fit for your app depends on how and where your app calls this method. Please show more code how you want to use this method.

WoW! This is awsome - thanks a lot, OOPer! I am using the first version in the onAppear event of a view to show a button or not and display the current status as a text. Works great!


The Combine framework is surely worth a look but I will keep that for a rainy day...


Cheers