gpt4 book ai didi

ios - 为什么 iOS 模拟器上不会触发通知?

转载 作者:行者123 更新时间:2023-11-30 10:56:55 25 4
gpt4 key购买 nike

本地通知过去常常在模拟器中为我触发,直到我基本上使用不同的数据模型重写了我的应用程序。现在,尽管似乎所有事情都发生了,但事实并非如此。

以下是我可以确认的按顺序显示在日志中的内容:

  • “用户已启用通知权限”

  • “用户启用的通知权限”

  • “尝试创建时间为 19:37 的闹钟”

  • “正在创建通知,日期:19,时间:19:36,uuid=B76AA489-CF41-49CB-9C3D-CF48590A9933”

  • “创建的警报附加了 1 个 notificationUuids”

  • "----- notificationUuids: -----"

  • “uuid:B76AA489-CF41-49CB-9C3D-CF48590A9933”

没有打印任何错误。这让我相信警报已正确创建,并且通知已添加到通知中心,但由于某种原因它没有触发。下面是我的代码,经过删节以减少不必要的复杂性。我只删除了与通知无关的内容。

class AlarmTableViewController: UITableViewController {

//MARK: Public properties
var alarms = [Alarm]()
let ALARM_CELL_IDENTIFIER = "AlarmTableViewCell"

override func viewDidLoad() {
super.viewDidLoad()
requestUserNotificationsPermissionsIfNeeded()
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didReceiveNotification), name: NotificationNames.randomAlarmNotification, object: nil)
loadAlarms()

for alarm in self.alarms {
os_log("There are %d notifications for alarm %d", log: OSLog.default, type: .debug, alarm.notificationUuids.count, alarm.alarmNumber)
}
}

deinit {
NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: NotificationNames.randomAlarmNotification, object: nil)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

guard let cell = tableView.dequeueReusableCell(withIdentifier: ALARM_CELL_IDENTIFIER, for: indexPath) as? AlarmTableViewCell else {
fatalError("The dequeued cell is not an instance of AlarmTableViewCell.")
}

guard let alarm = self.alarms[safe: indexPath.row] else {
os_log("Could not unwrap alarm for indexPath in AlarmTableViewController.swift", log: OSLog.default, type: .default)
self.tableView.reloadData()
return AlarmTableViewCell()
}

let alarmNumber = alarm.value(forKey: "alarmNumber") as! Int
cell.alarmNumberLabel.text = "Alarm " + String(alarmNumber)

let beginTime = alarm.value(forKey: "startTimeInterval") as! Double
let endTime = alarm.value(forKey: "endTimeInterval") as! Double
let beginTimeHour = Alarm.extractHourFromTimeDouble(alarmTimeDouble: beginTime)
let beginTimeMinute = Alarm.extractMinuteFromTimeDouble(alarmTimeDouble: beginTime)
cell.beginTimeLabel.text = formatTime(hour: beginTimeHour, minute: beginTimeMinute)
let endTimeHour = Alarm.extractHourFromTimeDouble(alarmTimeDouble: endTime)
let endTimeMinute = Alarm.extractMinuteFromTimeDouble(alarmTimeDouble: endTime)
cell.endTimeLabel.text = formatTime(hour: endTimeHour, minute: endTimeMinute)

guard let notificationUuids = self.getNotificationUuidsFromAlarmMO(alarm: alarm) else {
os_log("Could not get notificationUuids from AlarmMO in tableView(cellForRowAt:) in AlarmTableViewController.swift", log: OSLog.default, type: .debug)
return cell
}
os_log("----- notificationUuids: -----", log: OSLog.default, type: .debug)
for uuid in notificationUuids {
os_log("uuid: %@", log: OSLog.default, type: .debug, uuid)
}

return cell

}

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

let alarmNotificationIdentifier = response.notification.request.identifier
var alarmActedOn: Alarm? = nil
for alarm in self.alarms {
guard let notificationUuids = self.getNotificationUuidsFromAlarmMO(alarm: alarm) else {
os_log("Could not get notificationUuids from AlarmMO in tableView(forRowAt:) in AlarmTableViewController.swift", log: OSLog.default, type: .debug)
return
}
for notificationUuid in notificationUuids {
if notificationUuid == alarmNotificationIdentifier {
alarmActedOn = alarm
}
}
}
if response.actionIdentifier == "snooze" {
alarmActedOn?.setNewRandomAlarmTime()
}
completionHandler()

}

// MARK: Actions

@IBAction func unwindToAlarmList(sender: UIStoryboardSegue) {

if let sourceViewController = sender.source as? AddAlarmViewController, let alarm = sourceViewController.alarm {
let newIndexPath = IndexPath(row: self.alarms.count, section: 0)
os_log("There are %d notificationUuids attached to the alarm created", log: OSLog.default, type: .debug, alarm.notificationUuids.count)
saveAlarm(alarmToSave: alarm)
tableView.insertRows(at: [newIndexPath], with: .automatic)
}

}

// MARK: Private functions

@objc private func didReceiveNotification() {

os_log("entered the function", log: OSLog.default, type: .debug)

}

private func removeNotifications(notificationUuids: [String]) {

os_log("Removing %d alarm notifications", log: OSLog.default, type: .debug, notificationUuids.count)
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.removePendingNotificationRequests(withIdentifiers: notificationUuids)

}

private func loadAlarms() {

os_log("loadAlarms() called", log: OSLog.default, type: .debug)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<Alarm>(entityName: "Alarm")

do {
if self.alarms.count == 0 {
self.alarms = try managedContext.fetch(fetchRequest)
os_log("Loading %d alarms", log: OSLog.default, type: .debug, self.alarms.count)
} else {
os_log("Didn't need to load alarms", log: OSLog.default, type: .debug)
}
} catch let error as NSError {
print("Could not fetch alarms. \(error), \(error.userInfo)")
}

}

private func saveAlarm(alarmToSave: Alarm) {

guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Alarm", in: managedContext)!
let alarm = Alarm(entity: entity, insertInto: managedContext)

alarm.setValue(alarmToSave.alarmTime, forKeyPath: "alarmTime")
alarm.setValue(alarmToSave.alarmNumber, forKeyPath: "alarmNumber")
alarm.setValue(alarmToSave.startTimeInterval, forKeyPath: "startTimeInterval")
alarm.setValue(alarmToSave.endTimeInterval, forKeyPath: "endTimeInterval")
alarm.setValue(RecurrenceOptions.getRawValue(value: alarmToSave.recurrence), forKeyPath: "recurrenceIndex")
alarm.setValue(alarmToSave.notificationUuids, forKeyPath: "notificationUuids")
alarm.setValue(alarmToSave.note, forKeyPath: "note")

if managedContext.hasChanges {
do {
try managedContext.save()
self.alarms.append(alarm)
} catch let error as NSError {
print("Could not save alarm to CoreData. \(error), \(error.userInfo)")
}
} else {
os_log("No changes to the context to save", log: OSLog.default, type: .debug)
}

}

private func getNotificationUuidsFromAlarmMO(alarm: Alarm) -> [String]? {

guard let notificationUuids = alarm.value(forKey: "notificationUuids") as! [String]? else {
os_log("Found nil when attempting to unwrap notificationUuids in getNotificationUuidsFromAlarmMO() in AlarmTableViewController.swift, returning nil",
log: OSLog.default, type: .default)
return nil
}
return notificationUuids

}

private func requestUserNotificationsPermissionsIfNeeded() {

let notificationCenter = UNUserNotificationCenter.current()

notificationCenter.getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else {
return
}
os_log("User has notifications permissions enabled", log: OSLog.default, type: .debug)
}

notificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
if !granted {
self.presentNotificationsPermissionDenialConfirmationAlert()
} else {
os_log("User enabled notifications permissions", log: OSLog.default, type: .debug)
}
}

return

}

private func presentNotificationsPermissionDenialConfirmationAlert() {

let alert = UIAlertController(title: "Are you sure you don't want to allow notifications?",
message: "The application cannot function without notifications.", preferredStyle: .alert)

alert.addAction(UIAlertAction(title: "Yes", style: .cancel, handler: {
action in
fatalError("User declined to allow notifications permissions")
}))
alert.addAction(UIAlertAction(title: "No", style: .default, handler: {
action in
self.requestUserNotificationsPermissionsIfNeeded()
}))

self.present(alert, animated: true)

}

}

这是我的 AlarmTableViewController 代码。这是我的 Alarm.swift 代码:

class Alarm: NSManagedObject {

@NSManaged var alarmTime: Double
@NSManaged var alarmNumber: Int
@NSManaged var startTimeInterval: Double
@NSManaged var endTimeInterval: Double
@NSManaged var note: String
@NSManaged var notificationUuids: [String]
@NSManaged var recurrenceIndex: Int
let NUMBER_OF_ALLOWED_NOTIFICATIONS_CREATED_AT_ONE_TIME = 10

}

extension Alarm {

static func newAlarm(context: NSManagedObjectContext, alarmNumber: Int, timeIntervals: TimeIntervals, note: String, recurrence: RecurrenceOptions) -> Alarm? {

let startInterval = Alarm.convertToTimeDouble(hour: timeIntervals.hourStartInterval, minute: timeIntervals.minuteStartInterval)
let endInterval = Alarm.convertToTimeDouble(hour: timeIntervals.hourEndInterval, minute: timeIntervals.minuteEndInterval)

if endInterval < startInterval {
os_log("Error: Alarm time endInterval is before startInterval", log: OSLog.default, type: .info)
return nil
}
let newAlarm = Alarm(context: context)
newAlarm.alarmNumber = alarmNumber
newAlarm.note = note
newAlarm.recurrenceIndex = RecurrenceOptions.getRawValue(value: recurrence)
newAlarm.notificationUuids = [String]()
newAlarm.startTimeInterval = startInterval
newAlarm.endTimeInterval = endInterval

newAlarm.setNewRandomAlarmTime()

return newAlarm
}

var recurrence: RecurrenceOptions {
get {
return RecurrenceOptions.getValueFromIndex(index: recurrenceIndex)
}

set {
self.recurrenceIndex = RecurrenceOptions.getRawValue(value: newValue)
}
}

var hour: Int {
return Int(floor(self.alarmTime))
}

var minute: Int {
return Int(round((self.alarmTime - floor(self.alarmTime)) * 60))
}

func setNewRandomAlarmTime() {

let startInterval = self.startTimeInterval
let endInterval = self.endTimeInterval

let currentDateAndTime = Date()
let currentDateAndTimeComponents = Calendar.current.dateComponents([.hour, .minute], from: currentDateAndTime)
guard let currentHour = currentDateAndTimeComponents.hour else {
os_log("Could not unwrap currentDateAndTimeComponents.hour in Alarm.setNewRandomAlarmTime()", log: OSLog.default, type: .default)
return
}
guard let currentMinute = currentDateAndTimeComponents.minute else {
os_log("Could not unwrap currentDateAndTimeComponents.minute in Alarm.setNewRandomAlarmTime()", log: OSLog.default, type: .default)
return
}
let currentTimeDouble = Alarm.convertToTimeDouble(hour: currentHour, minute: currentMinute)

// We should start the random alarm interval from the current
// time if the current time is past the startInterval already
if currentTimeDouble > startInterval {
self.alarmTime = Double.random(in: currentTimeDouble ... endInterval)
} else {
self.alarmTime = Double.random(in: startInterval ... endInterval)
}

scheduleNotifications()

}

func scheduleNotifications() {
os_log("Attempting to create alarm with time %d:%02d", log: OSLog.default, type: .info, self.hour, self.minute)
let date = Date()
let calendar = Calendar.current
let currentDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: date)
createNotifications(dateComponents: currentDateComponents)
}

//MARK: Private functions

private func createNotifications(dateComponents: DateComponents) {

switch (self.recurrence) {
case .today:
self.createNotification(for: dateComponents)
case .tomorrow:
self.createNotification(for: self.day(after: dateComponents))
case .daily:
var numberOfCreatedNotifications = 0
var currentDay: DateComponents? = dateComponents
while numberOfCreatedNotifications < self.NUMBER_OF_ALLOWED_NOTIFICATIONS_CREATED_AT_ONE_TIME {
self.createNotification(for: currentDay)
currentDay = self.day(after: currentDay)
numberOfCreatedNotifications += 1
}
}

}

private func createNotification(for dateComponents: DateComponents?) {

let center = UNUserNotificationCenter.current()

let content = UNMutableNotificationContent()
content.title = "Random Alarm"
content.subtitle = "It's time!"
content.body = self.note
content.sound = UNNotificationSound.default

guard let dateComponents = dateComponents else {
os_log("Could not unwrap dateComponents in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)

let uuidString = UUID().uuidString
let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: trigger)
self.notificationUuids.append(uuidString)

guard let day = dateComponents.day else {
os_log("Could not unwrap dateComponents.day in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
guard let hour = dateComponents.hour else {
os_log("Could not unwrap dateComponents.hour in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
guard let minute = dateComponents.minute else {
os_log("Could not unwrap dateComponents.minute in createNotification() in Alarm.swift", log: OSLog.default, type: .debug)
return
}
os_log("Creating notification for day: %d, time: %d:%02d, with uuid=%s", log: OSLog.default, type: .debug, day, hour, minute, uuidString)

center.add(request) { (error) in
if let err = error {
print("error \(err.localizedDescription)")
}
}

}

private func day(after dateComponents: DateComponents?) -> DateComponents? {

let calendar = Calendar.autoupdatingCurrent

guard let dateComponents = dateComponents,
let date = calendar.date(from: dateComponents),
let tomorrow = calendar.date(byAdding: .day, value: 1, to: date)
else {
os_log("Could not calculate tomorrow in Alarm.swift", log: OSLog.default, type: .debug)
return nil
}
let newDateComponents = calendar.dateComponents([.year, .month, .day, .timeZone, .hour, .minute], from: tomorrow)
return newDateComponents

}

}

最佳答案

我明白了。在 Alarm.swift 的 createNotification() 中,我正在创建当前时间的通知,而不是随机闹钟时间。简单的错误,但这意味着闹钟时间在间隔之前结束,一旦您重新打开应用程序,它就会删除闹钟,因为它是“旧的”。

关于ios - 为什么 iOS 模拟器上不会触发通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53861638/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com