Отображение запланированных уведомлений в контроллере табличного представления - PullRequest
0 голосов
/ 09 февраля 2019

Я пытаюсь перечислить все уведомления, созданные пользователем и запланированные в моем приложении, аналогично списку сигналов тревоги в приложении «Часы» от Apple.Однако каждый раз, когда я получаю массив уведомлений и пытаюсь их отобразить, они не отображаются правильно все время.

Каждое уведомление повторяется каждый день в одно и то же время, поэтому я использую UNUserNotificationCenter.current().getPendingNotificationRequestsполучить массив уведомлений.С этим массивом уведомлений я перебираю каждое уведомление, создаю новый пользовательский объект «Напоминание» и добавляю его в мой массив «Напоминаний», который я использую при отображении уведомлений в контроллере табличного представления.

Я делаю это каждый раз, используя функцию viewWillAppear.

Вот код:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    generateReminders()

    tableView.reloadData()
}

func generateReminders()
{
    let center = UNUserNotificationCenter.current()
    center.getPendingNotificationRequests { (notifications) in
        for item in notifications {
            if let trigger = item.trigger as? UNCalendarNotificationTrigger,
                let triggerDate = trigger.nextTriggerDate() {
                var withSound = true
                if(item.content.sound != UNNotificationSound.default)
                {
                    withSound = false
                }
                self.reminders.append(Reminder(identifier: item.identifier, time: triggerDate, message: item.content.body, withSound: withSound, isAPendingNotification: true))
            }
        }
        self.remindersCount = notifications.count
    }
}

Когда ячейки будут отображаться в контроллере табличного представления,Я использую массив «Напоминание», чтобы настроить каждую ячейку для отображения информации уведомления.Все это делается в функции 'cellForRowAt', код ниже.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Reminder", for: indexPath)
    var text = ""
    var detailText = ""

    if(indexPath.row < remindersCount) {
        let reminder = reminders[indexPath.row]
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm"

        text = formatter.string(from: reminder.Time)
        detailText = reminder.Message
    }

    cell.textLabel?.text = text
    cell.detailTextLabel?.text = detailText

    return cell
}

Когда пользователь выбирает для просмотра другую вкладку, я сбрасываю объект «напоминания» на пустой, чтобы при возврате на эту вкладкуотображается обновленный массив уведомлений, код которого приведен ниже.

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    reminders = [Reminder]()
    remindersCount = 0
    tableView.setNeedsDisplay()
}

Проблема, с которой я сталкиваюсь, заключается в том, что это крайне противоречиво, иногда отображаются все уведомления, иногда отображаются только некоторые, а в других случаях ни одно из нихотображаются.Однако каждый раз, когда я распечатываю счетчик количества уведомлений в методе UNUserNotificationCenter.current().getPendingNotificationRequests, это всегда правильный номер.Кроме того, всякий раз, когда я нажимаю на ячейку, которая должна содержать информацию об уведомлении, информация там есть, она просто не отображается.

Вот короткое видео об этих проблемах.

https://imgur.com/1RVerZD

Я не уверен, как это исправить, я попытался запустить код в главной очереди ив глобальной очереди с качеством обслуживания, установленным в «.userInteractive», как показано ниже, но все еще без кубиков.

let center = UNUserNotificationCenter.current()
    let dq = DispatchQueue.global(qos: .userInteractive)
    dq.async {
        center.getPendingNotificationRequests { (notifications) in
            for item in notifications {
                if let trigger = item.trigger as? UNCalendarNotificationTrigger,
                    let triggerDate = trigger.nextTriggerDate() {
                    var withSound = true
                    if(item.content.sound != UNNotificationSound.default)
                    {
                        withSound = false
                    }
                    self.reminders.append(Reminder(identifier: item.identifier, time: triggerDate, message: item.content.body, withSound: withSound, isAPendingNotification: true))
                }
            }
            self.remindersCount = notifications.count
        }
    }

Небольшое приложение с этой проблемой можно загрузить из этого репозитория Github.

https://github.com/AlexMarchant98/LitstingNotificationsIssue

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

В вашем коде tableview есть некоторые проблемы, перечисленные ниже.

  1. Вы использовали статические ячейки в табличном представлении, что неправильно, если у вас есть динамические строки.

Предложение : Используйте Динамическая ячейка прототипа для tableview.

remindersCount вообще не требуется, поскольку он уже есть в вашем массиве.

Предложение : Используйте self.reminders.count для подсчета массива.

unwindToRemindersTableViewController() метод имеет generateReminders() вызов, который не требуется, так как viewWillAppear() будет вызывать при отклонении представления.

Предложение : проверка ViewController жизненный цикл, вы получите правильное представление о том, как перезагрузить данные.

Я обновил некоторый код в вашем примере проекта.

Пожалуйста, найдите обновленный код здесь .

Github обновил демо

Надеюсь, это поможет!

0 голосов
/ 12 февраля 2019

Проблема с вашим кодом - это время выполнения tableView.reloadData().

UNUserNotificationCenter.current().getPendingNotificationRequests() - это асинхронный вызов, и поэтому массив reminders заполняется после tableView.reloadData()был вызван.

Перемещение tableView.reloadData() в конец блока обратного вызова getPendingNotificationRequests() должно исправить вашу проблему.(И не забудьте вызвать reloadData() из основного потока)

func generateReminders()
{
    let center = UNUserNotificationCenter.current()
    let dq = DispatchQueue.global(qos: .userInteractive)
    dq.async {
        center.getPendingNotificationRequests { (notifications) in
            for item in notifications {
                if let trigger = item.trigger as? UNCalendarNotificationTrigger,
                    let triggerDate = trigger.nextTriggerDate() {
                    var withSound = true
                    if(item.content.sound != UNNotificationSound.default)
                    {
                        withSound = false
                    }
                    self.reminders.append(Reminder(identifier: item.identifier, time: triggerDate, message: item.content.body, withSound: withSound, isAPendingNotification: true))
                }
            }

            self.remindersCount = notifications.count

            DispatchQueue.main.async {
                self.tableView.reloadData() // <---------
            }
        }
    }
}
...