127 lines
4.3 KiB
Swift
127 lines
4.3 KiB
Swift
//
|
||
// TimeSpecificNotificationManager.swift
|
||
// SHECommunity
|
||
//
|
||
// Created by Lin on 2025/7/29.
|
||
//
|
||
|
||
import UIKit
|
||
import UserNotifications
|
||
|
||
class TimeSpecificNotificationManager {
|
||
static let shared = TimeSpecificNotificationManager()
|
||
private init() {}
|
||
|
||
// 1. 请求通知权限(必须先调用)
|
||
func requestNotificationPermission() {
|
||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
|
||
if granted {
|
||
print("通知权限已允许")
|
||
} else {
|
||
print("通知权限被拒绝,无法发送通知")
|
||
}
|
||
}
|
||
}
|
||
|
||
// 2. 发送指定时间的本地通知(一次性)
|
||
/// - Parameters:
|
||
/// - title: 通知标题
|
||
/// - body: 通知内容
|
||
/// - date: 触发的具体日期时间(如 2025-08-01 09:30:00)
|
||
/// - identifier: 通知唯一标识(用于后续取消等操作)
|
||
func scheduleOneTimeNotification(
|
||
title: String,
|
||
body: String,
|
||
at date: Date,
|
||
identifier: String = UUID().uuidString
|
||
) {
|
||
// 创建通知内容
|
||
let content = UNMutableNotificationContent()
|
||
content.title = title
|
||
content.body = body
|
||
content.sound = .default // 通知声音
|
||
content.badge = 1 // 应用图标角标
|
||
|
||
// 将 Date 转换为 DateComponents(提取年月日时分)
|
||
let components = Calendar.current.dateComponents(
|
||
[.year, .month, .day, .hour, .minute], // 精确到分钟(忽略秒和毫秒)
|
||
from: date
|
||
)
|
||
|
||
// 创建日历触发器(一次性)
|
||
let trigger = UNCalendarNotificationTrigger(
|
||
dateMatching: components,
|
||
repeats: false // 仅触发一次
|
||
)
|
||
|
||
// 创建通知请求
|
||
let request = UNNotificationRequest(
|
||
identifier: identifier,
|
||
content: content,
|
||
trigger: trigger
|
||
)
|
||
|
||
// 添加通知到系统
|
||
UNUserNotificationCenter.current().add(request) { error in
|
||
if let error = error {
|
||
print("通知添加失败:\(error.localizedDescription)")
|
||
} else {
|
||
print("通知已设置,将在 \(date) 触发")
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. 发送重复的指定时间通知(如每天同一时间)
|
||
/// - Parameters:
|
||
/// - title: 通知标题
|
||
/// - body: 通知内容
|
||
/// - hour: 小时(24小时制,如 9 表示上午9点)
|
||
/// - minute: 分钟(如 30 表示30分)
|
||
/// - identifier: 通知唯一标识
|
||
func scheduleRepeatingNotification(
|
||
title: String,
|
||
body: String,
|
||
hour: Int,
|
||
minute: Int,
|
||
identifier: String = UUID().uuidString
|
||
) {
|
||
let content = UNMutableNotificationContent()
|
||
content.title = title
|
||
content.body = body
|
||
content.sound = .default
|
||
content.badge = 1
|
||
|
||
// 设置触发时间(忽略年/月/日,仅保留时/分,配合 repeats: true 实现每天重复)
|
||
var dateComponents = DateComponents()
|
||
dateComponents.hour = hour // 例如:9(上午9点)
|
||
dateComponents.minute = minute // 例如:30(30分)
|
||
|
||
// 创建日历触发器(每天重复)
|
||
let trigger = UNCalendarNotificationTrigger(
|
||
dateMatching: dateComponents,
|
||
repeats: true // 重复触发(根据 dateComponents 中的粒度,此处为每天)
|
||
)
|
||
|
||
// 添加通知请求
|
||
let request = UNNotificationRequest(
|
||
identifier: identifier,
|
||
content: content,
|
||
trigger: trigger
|
||
)
|
||
|
||
UNUserNotificationCenter.current().add(request) { error in
|
||
if let error = error {
|
||
print("重复通知添加失败:\(error.localizedDescription)")
|
||
} else {
|
||
print("每天 \(hour):\(minute) 的重复通知已设置")
|
||
}
|
||
}
|
||
}
|
||
|
||
// 4. 取消指定标识的通知(用于取消已设置的定时通知)
|
||
func cancelNotification(identifier: String) {
|
||
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [identifier])
|
||
print("已取消标识为 \(identifier) 的通知")
|
||
}
|
||
}
|