“推送通知”开关可以检测应用程序的当前授权?

问题描述 投票:0回答:1

我想在我的 SettingsView 中添加一个多功能的“推送通知”开关。

通过多功能,我的意思是,如果应用程序的通知当前权限是授权的、临时的或临时的,我希望切换自动设置为启用。如果被拒绝或未确定则禁用。

理想情况下,如果设置为“未确定”,切换也会请求权限。如果设置为“拒绝”,则发送到应用程序设置。

我的 SettingsView 的片段

struct SettingsView: View {
    let notify = NotificationHandler()
    @State private var enablePushNotifications = false

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Notifications")) {
                    let toggle = Binding<Bool> (
                        get: { self.enablePushNotifications }
                        set: { newValue in
                            self.enablePushNotifications = newValue
                            })

                    Toggle("Push Notifications", isOn: toggle)
             }
        }
    }
}
ios swift xcode swiftui push-notification
1个回答
0
投票

您无法以编程方式从通知中“取消授权”,因此我假设您在

@AppStorage
或其他位置存储了一个标志,指示用户是否更喜欢收到通知。

@AppStorage("notifications") var shouldSendNotifications = true

仅当

shouldSendNotifications
为 true 并且 用户已授权您的应用程序时,您才应发送通知。

然后,您需要做的就是使用

notificationSettings
获取当前的授权状态,并用您获得的状态更新一些
@State
。您可以在
task(id:)
块中运行此代码,这样您只需更改
id
即可重新运行它。

@preconcurrency import UserNotifications

struct ContentView: View {
    @State private var notificationAuthorised = false
    @State private var taskTrigger = false
    @Environment(\.scenePhase) var scenePhase
    @AppStorage("notifications") var shouldSendNotifications = true
    
    var body: some View {
        Form {
            Section(header: Text("Notifications")) {
                let binding = Binding {
                    notificationAuthorised && shouldSendNotifications
                } set: { newValue in
                    if newValue { // turning on notifications
                        Task {
                            // perhaps also UIApplication.shared.registerForRemoteNotifications()
                            shouldSendNotifications = true

                            let notifCenter = UNUserNotificationCenter.current()
                            let settings = await notifCenter.notificationSettings()
                            if settings.authorizationStatus == .notDetermined {
                                // show the request alert
                                try await notifCenter.requestAuthorization(options: [.alert, .sound, .badge])
                            } else if settings.authorizationStatus == .denied {
                                // go to settings page
                                if let appSettings = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(appSettings) {
                                    await UIApplication.shared.open(appSettings)
                                }
                            }
                            // run the task again to update notificationAuthorised
                            taskTrigger.toggle()
                        }
                    } else {
                        shouldSendNotifications = false
                        // perhaps also UIApplication.shared.unregisterForRemoteNotifications()
                    }
                }

                Toggle("Push Notifications", isOn: binding)
            }
        }
        .task(id: taskTrigger) {
            let notifCenter = UNUserNotificationCenter.current()
            let settings = await notifCenter.notificationSettings()
            switch settings.authorizationStatus {
            case .notDetermined, .denied:
                notificationAuthorised = false
            case .authorized, .ephemeral, .provisional:
                notificationAuthorised = true
            @unknown default:
                notificationAuthorised = false
            }
        }
        // run the task again to update notificationAuthorised when coming back to the app
        .onChange(of: scenePhase) {
            taskTrigger.toggle()
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.