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
相关产品推荐
相关产品推荐

