I’m looking to create a property that will track the user’s notification authorization setting for the application. (The ultimate goal here is to alert the user if they ask for a notification but have declined to receive them from the app.) I’ve tried a variety of solutions, to no avail. The code below throws an error that says "Cannot convert return expression of type ‘Void’ to return type ‘String’".
class LocalNotificationScheduler {
var notificationAuthStatus: String {
UNUserNotificationCenter.current().getNotificationSettings { settings in
switch settings.authorizationStatus {
case .authorized:
return "authorized"
case .provisional:
return "provisional"
case .notDetermined:
return "notDetermined"
case .denied:
return "denied"
default:
break
} // End of "switch settings.authorizationStatus {"
} // End of "{ settings in"
}
private func requestAuthorization() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted == true && error == nil {
self.scheduleNotification()
}
}
} // End of requestAuthorization() func
func schedulingRequested() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
switch settings.authorizationStatus {
case .notDetermined:
self.requestAuthorization()
case .authorized, .provisional:
self.scheduleNotification()
case .denied:
print("Conflict between request for notification and app permissions!")
default:
break
}
}
} // End of schedule() func
private func scheduleNotification() {
let content = UNMutableNotificationContent()
content.title = "Scheduled notification"
content.body = "Test"
content.sound = .default
// Trigger
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
let request = UNNotificationRequest(identifier: "test", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
guard error == nil else { return }
}
} // End of scheduleNotification() func
// MARK: - Life Cycle
init() {
} // End of init()
}
struct ContentView: View {
// MARK: - Properties
// Alert the user that there's a conflict between their request for a notification and the app permissions
@State var notificationConflict: Bool = false
// MARK: - View
var body: some View {
Form {
Button("Send notification") {
let notificationScheduler = LocalNotificationScheduler()
print("Step 1: notificationScheduler.notificationAuthStatus = (notificationScheduler.notificationAuthStatus)")
if notificationScheduler.notificationAuthStatus == "denied" {
notificationConflict = true
print("Step 2a: notificationScheduler.notificationAuthStatus WAS denied so...")
print("notificationConflict = (notificationConflict)")
} else {
print("Step 2b: notificationScheduler.notificationAuthStatus was NOT denied so scheduling notification")
notificationScheduler.schedulingRequested()
}
print("Step 3: notificationScheduler.notificationAuthStatus = (notificationScheduler.notificationAuthStatus)")
print("Step 3: notificationConflict = (notificationConflict)")
}
} // End of Form
} // End of body view
}
I’ve also tried to creating a function that looks a lot like the code above but sets the value of notificationAuthStatus
rather than returning it. The function doesn’t throw an error, but it runs asynchronously such that the value of notificationAuthStatus
is not set when I need to use it.
Any advice about how to proceed is much appreciated!
2
Answers
I think I've come up with a solution that works for my purposes. I'm posting it here in case anyone else has the same challenge and stumbles upon this question. Here's what worked for me:
Here's my LocalNotificationScheduler code:
And the View code:
So, that's my current solution. If there's a better way to do all this, I'd welcome the input!
This compiles:
but I don’t know if this suffices for your code as you don’t show it in context, so we don’t know how you are using it.
If you are using it in a notification controller class to see if you have authorization, or need to request authorization, why not jus use it directly instead of returning a string?