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

iOS16+ SwiftUI中重置应用图标角标数为0失败求助

解决iOS 16+应用重新打开时角标无法清零的问题

问题原因

你当前仅在ContentView的onAppear中调用重置角标的方法,但onAppear仅在视图首次加载时触发。当应用从后台重新打开(比如按Home键返回桌面后再次启动),ContentView已存在于视图层级中,onAppear不会再次执行,导致重置逻辑未触发。

另外,虽然UNUserNotificationCenter.setBadgeCount(_:)是iOS 16+的推荐API,但UI相关操作需保证在主线程执行,这是系统最佳实践。

解决方案

1. 监听应用前台状态

使用SwiftUI的scenePhase环境变量,监听应用进入前台(.active状态)的事件,每次应用激活时都执行角标重置。

2. 确保主线程执行

将重置角标的逻辑包裹在DispatchQueue.main.async中,保证操作在主线程完成。

修改后的完整代码

import SwiftUI
import UserNotifications

class NotificationManager{
    static let instance = NotificationManager()
    
    func requestAuth(){
        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options: [.alert, .sound, .badge, .provisional]) { granted, error in
            if let error = error {
                print("Error: \(error)")
            } else {
                print("Authorization granted")
            }
        }
    }
    
    func scheduleNoti(){
        let content = UNMutableNotificationContent()
        content.title = "This is my first Notification"
        content.subtitle = "This is a sample body"
        content.sound = .default
        content.badge = 1
        
        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5.0, repeats: false)
        let req = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
        
        UNUserNotificationCenter.current().add(req)
    }

    func resetBadgeCount(){
        // 确保在主线程执行
        DispatchQueue.main.async {
            UNUserNotificationCenter.current().setBadgeCount(0) { error in
                if let error = error {
                    print("Reset badge error: \(error)")
                } else {
                    print("Badge count reset to 0")
                }
            }
        }
    }
}

struct ContentView: View {
    // 获取scenePhase环境变量
    @Environment(\.scenePhase) private var scenePhase
    
    var body: some View {
        VStack (spacing: 40){
            Button("Request Authorization"){
                NotificationManager.instance.requestAuth()
            }
            Button("Schedule Notification"){
                NotificationManager.instance.scheduleNoti()
            }
        }
        .onChange(of: scenePhase) { oldPhase, newPhase in
            // 当应用进入前台时重置角标
            if newPhase == .active {
                NotificationManager.instance.resetBadgeCount()
            }
        }
        .onAppear{
            // 首次加载时也重置一次
            NotificationManager.instance.resetBadgeCount()
        }
    }
}

#Preview {
    ContentView()
}

额外验证点

  • 确认用户已授权通知的badge权限:可以在requestAuth的回调中打印granted值,或者在系统设置中查看应用的通知权限是否开启了badge。
  • 如需兼容iOS 16之前的系统,可通过版本判断做兼容:
    func resetBadgeCount(){
        DispatchQueue.main.async {
            if #available(iOS 16.0, *) {
                UNUserNotificationCenter.current().setBadgeCount(0) { error in
                    // 处理错误
                }
            } else {
                UIApplication.shared.applicationIconBadgeNumber = 0
            }
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:23:20