You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI实现适配权限状态的Push Notifications多功能开关

实现权限感知的Push Notifications开关

步骤1:完善NotificationHandler类

首先扩展你的NotificationHandler,使其支持权限状态监听、更新,同时添加权限请求、跳转设置的方法:

import UserNotifications
import Combine

class NotificationHandler: ObservableObject {
    @Published var authorizationStatus: UNAuthorizationStatus = .notDetermined
    private var cancellables = Set<AnyCancellable>()
    
    init() {
        fetchAuthorizationStatus()
        // iOS 16+ 自动监听权限变化
        if #available(iOS 16.0, *) {
            UNUserNotificationCenter.current().notificationSettings()
                .receive(on: DispatchQueue.main)
                .sink { [weak self] settings in
                    self?.authorizationStatus = settings.authorizationStatus
                }
                .store(in: &cancellables)
        }
    }
    
    // 获取当前权限状态
    func fetchAuthorizationStatus() {
        UNUserNotificationCenter.current().getNotificationSettings { [weak self] settings in
            DispatchQueue.main.async {
                self?.authorizationStatus = settings.authorizationStatus
            }
        }
    }
    
    // 请求通知权限
    func requestAuthorization() async throws {
        _ = try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])
        fetchAuthorizationStatus()
    }
    
    // 跳转至应用设置页面
    func openAppSettings() {
        guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else { return }
        UIApplication.shared.open(settingsURL)
    }
}

步骤2:重构SettingsView

修改你的SettingsView,绑定权限状态,实现开关的自动更新和点击逻辑:

struct SettingsView: View {
    @StateObject private var notify = NotificationHandler()
    @State private var pushToggleEnabled = false
    
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Notifications")) {
                    Toggle("Push Notifications", isOn: $pushToggleEnabled)
                        // 权限变化时自动更新开关状态
                        .onChange(of: notify.authorizationStatus) { newStatus in
                            pushToggleEnabled = [.authorized, .provisional, .ephemeral].contains(newStatus)
                        }
                        // 处理用户点击开关的行为
                        .onChange(of: pushToggleEnabled) { newValue in
                            guard newValue else { return }
                            switch notify.authorizationStatus {
                            case .notDetermined:
                                Task {
                                    try? await notify.requestAuthorization()
                                }
                            case .denied:
                                notify.openAppSettings()
                            default:
                                // 权限已授权,可根据需求添加额外逻辑
                                break
                            }
                        }
                        // 页面加载时初始化开关状态
                        .onAppear {
                            pushToggleEnabled = [.authorized, .provisional, .ephemeral].contains(notify.authorizationStatus)
                        }
                }
            }
            .navigationTitle("Settings")
        }
    }
}

关键逻辑说明

  • 状态同步:开关的pushToggleEnabled状态会根据当前通知权限自动更新,仅当权限为authorized/provisional/ephemeral时显示为开启。
  • 点击处理:
    • 若权限为notDetermined,点击开关会触发通知权限请求。
    • 若权限为denied,点击开关会直接跳转至应用系统设置页面,引导用户手动开启权限。
    • 已授权状态下,开关保持开启,可根据业务需求添加本地通知开关的额外逻辑。
  • 兼容性:针对iOS 16+实现了权限自动监听,iOS 15及以下会在权限请求后手动更新状态。

注意事项

  • 确保在Info.plist中配置NSNotificationUsageDescription(iOS 10+),否则权限请求会被系统拒绝。
  • 权限请求的错误处理可根据项目需求补充,示例中使用try?简化处理。

内容的提问来源于stack exchange,提问作者Zack A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 15:30:19