如何实现提醒触发后实时自动更新FirstVC中UITableViewCell的提醒图标状态
解决提醒触发后实时移除FirstVC中Cell图标问题
首先,你目前通过进入SecondVC时比较时间的方式属于被动更新,要实现实时移除图标,核心是在通知触发的那一刻就同步更新数据模型并通知FirstVC刷新UI。下面是具体的实现步骤:
1. 监听通知触发事件
当系统触发你的提醒通知时,不管App是在前台还是后台,我们都能通过UNUserNotificationCenter的代理方法捕获这个事件。
步骤1:设置通知中心代理
在AppDelegate或者SceneDelegate中(根据你的iOS版本),先设置代理并请求通知权限:
import UserNotifications func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UNUserNotificationCenter.current().delegate = self // 请求通知权限 UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in if granted { print("通知权限已获取") } } return true }
步骤2:处理通知触发回调
实现UNUserNotificationCenterDelegate的两个关键方法,分别处理前台和后台/锁屏状态下的通知:
extension AppDelegate: UNUserNotificationCenterDelegate { // App在前台时收到通知的处理 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { handleTriggeredReminder(notification: notification) // 可以选择显示通知弹窗 completionHandler([.banner, .sound]) } // 用户点击通知后的处理(后台/锁屏状态) func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { handleTriggeredReminder(notification: response.notification) completionHandler() } // 统一处理提醒触发的逻辑 private func handleTriggeredReminder(notification: UNNotification) { // 从通知的userInfo中获取任务ID(设置提醒时要把任务ID存进去) guard let taskId = notification.request.content.userInfo["taskId"] as? String else { return } // 1. 更新你的数据模型:找到对应任务,标记提醒已触发 // 假设你用Core Data存储任务,这里示例简化处理 if let task = yourTaskStorage.getTask(withId: taskId) { task.hasActiveReminder = false yourTaskStorage.saveContext() } // 2. 发送自定义通知,告诉FirstVC需要刷新UI NotificationCenter.default.post(name: NSNotification.Name("ReminderTriggered"), object: taskId) } }
2. 在FirstVC中监听自定义通知并刷新UI
在FirstVC中,我们需要监听上面发送的自定义通知,收到后找到对应的Cell并移除图标:
class FirstVC: UIViewController, UITableViewDataSource, UITableViewDelegate { var tasks: [Task] = [] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // 注册自定义通知监听 NotificationCenter.default.addObserver(self, selector: #selector(handleReminderTriggered(_:)), name: NSNotification.Name("ReminderTriggered"), object: nil) } deinit { // 移除监听,避免内存泄漏 NotificationCenter.default.removeObserver(self) } @objc private func handleReminderTriggered(_ notification: Notification) { guard let taskId = notification.object as? String else { return } // 找到对应任务在数组中的索引 if let index = tasks.firstIndex(where: { $0.id == taskId }) { // 更新本地数组 tasks[index].hasActiveReminder = false // 刷新对应的Cell tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } } // UITableViewDataSource方法中,根据hasActiveReminder判断是否显示图标 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell let task = tasks[indexPath.row] cell.iconImageView.isHidden = !task.hasActiveReminder // 其他Cell配置... return cell } }
3. 设置提醒时记得传入任务ID
在SecondVC设置提醒的时候,一定要把任务的唯一ID存入通知的userInfo,这样触发时才能定位到对应的任务:
func setReminder(for task: Task, date: Date) { let content = UNMutableNotificationContent() content.title = "任务提醒" content.body = task.title // 存入任务ID content.userInfo["taskId"] = task.id let dateComponents = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute], from: date) let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false) let request = UNNotificationRequest(identifier: task.id, content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) { error in if let error = error { print("设置提醒失败:\(error)") } else { // 更新任务的提醒状态 task.hasActiveReminder = true yourTaskStorage.saveContext() } } }
额外注意点
- 如果App被杀死状态下触发通知,用户点击通知打开App时,
didReceive response方法会被调用,同样能触发更新逻辑 - 确保你的数据存储(Core Data/UserDefaults等)是线程安全的,避免更新时出现问题
- 自定义通知的名称建议用全局常量,避免拼写错误
内容的提问来源于stack exchange,提问作者Osama Naeem
相关产品推荐
相关产品推荐

