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

请校验:这段iOS通知代码能否每月固定日期推送通知?

代码功能校验与改进建议

你的代码仅能在有31天的月份触发通知,但存在几个关键问题会导致功能不符合预期,以下是具体分析和修正方案:

核心问题分析

  • 月份天数适配问题:你设置了dateComponents.day = 31,但2月、4月、6月、9月、11月这些没有31天的月份,通知会直接跳过,不会在当月触发。
  • 空通知标识符:UNNotificationRequest的identifier设为空字符串,后续无法精准更新、移除这个通知,还会和其他空标识符的通知产生冲突。
  • 缺失错误处理:请求权限时只判断了success,没有处理error,无法排查权限请求失败的具体原因。
  • 时区未显式指定:DateComponents默认使用设备当前时区,若用户切换时区,触发时间可能偏离预期,最好显式指定时区。

修正后的代码

static func addMonthlyNotification() {
    let center = UNUserNotificationCenter.current()
    
    let addRequest = {
        let content = UNMutableNotificationContent()
        content.title = "Test"
        content.subtitle = "Test"
        content.sound = UNNotificationSound.default
        
        var dateComponents = DateComponents()
        // 处理小月的情况:若目标日期超过当月天数,系统会自动取当月最后一天触发
        dateComponents.day = 31
        dateComponents.hour = 12
        dateComponents.timeZone = TimeZone.current // 显式指定时区
        
        let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
        
        // 使用唯一标识符,方便后续管理通知
        let request = UNNotificationRequest(identifier: "MonthlyTestNotification", content: content, trigger: trigger)
        center.add(request) { error in
            if let error = error {
                print("添加通知失败: \(error.localizedDescription)")
            }
        }
    }
    
    center.getNotificationSettings { settings in
        switch settings.authorizationStatus {
        case .authorized:
            addRequest()
        case .notDetermined:
            center.requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
                if success {
                    addRequest()
                } else if let error = error {
                    print("请求通知权限失败: \(error.localizedDescription)")
                }
            }
        default:
            print("通知权限未授权")
        }
    }
}

额外优化思路

如果你的需求是每月最后一天触发通知,可以通过计算当月最后一天的日期组件来替代固定设为31日,完美适配所有月份,示例逻辑如下:

// 获取当前月份的最后一天
let calendar = Calendar.current
let today = Date()
let lastDayOfMonth = calendar.date(byAdding: .month, value: 1, to: calendar.startOfDay(for: today))!
let lastDayComponents = calendar.dateComponents([.day, .hour], from: lastDayOfMonth)
dateComponents.day = lastDayComponents.day
dateComponents.hour = 12

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:20:36