Переключатель «Push-уведомления», который может определить текущую авторизацию приложения?

Я хотел бы добавить универсальный переключатель «Push-уведомления» в свой 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)
             }
        }
    }
}

Обратите внимание: NavigationView устарел, вам следует использовать NavigationStack. Почему бы не использовать enablePushNotifications напрямую, например Toggle("Push Notifications", isOn: $enablePushNotifications).

workingdog support Ukraine 25.05.2024 04:22

Спасибо! Я был в стороне от девальвации. Я обновился, чтобы использовать NavigationStack.

Zack A 25.05.2024 22:14
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
110
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете программно «отключить» себя от уведомлений, поэтому я предполагаю, что у вас есть флаг, хранящийся в @AppStorage или где-то еще, который указывает, предпочитает ли пользователь получать уведомления.

@AppStorage("notifications") var shouldSendNotifications = true

Отправлять уведомления следует только тогда, когда shouldSendNotifications истинно и пользователь авторизовал ваше приложение.

Затем все, что вам нужно сделать, это получить текущий статус авторизации с помощью Настройки уведомлений и обновить некоторые @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()
        }
    }
}

Это именно то решение, которое мне было нужно! Мой переключатель уведомлений теперь универсален :)

Zack A 25.05.2024 22:32

Другие вопросы по теме

Похожие вопросы