Переход с UILocalNotification на UNUserNotification быстро

Я перехожу на NUUserNotification, но у меня возникают проблемы, так как я изучаю уведомления с новой структурой, а старую я не знаю. Я надеюсь, что это не какой-то дубликат, поскольку я прочитал много сообщений и руководств по миграции, но не нашел чего-то, что помогло бы мне понять, как применить в этом случае. Код, который я обновляю, не мой, и мне потребовалось время, чтобы разобраться в нем. Это клон iOS Alarm (https://github.com/natsu1211/Alarm-ios-swift), который я включаю в свое приложение для выполнения действий в запланированное время / дни и т. д. сейчас на каждый рабочий день или на одно время, верно? Параметр fireDate обесценился, как бы мне его переписать? :

private func minFireDateWithIndex(notifications: [UILocalNotification]) -> (Date, Int)? {
    if notifications.isEmpty {
        return nil
    }
    var minIndex = -1
    var minDate: Date = notifications.first!.fireDate!
    for n in notifications {
        let index = n.userInfo!["index"] as! Int
        if(n.fireDate! <= minDate) {
            minDate = n.fireDate!
            minIndex = index
        }
    }
    return (minDate, minIndex)
}

Другой код, который у меня возникают при обновлении, - это проверка существующих уведомлений, которые теперь getPendingNotificationRequestsWithCompletionHandler:]. Это if let n = UIApplication.shared.scheduledLocalNotifications внутри старой функции, определяющей уведомление, которую, я думаю, я обновил для оставшейся части. Старый код:

func setupNotificationSettings() -> UIUserNotificationSettings {

        var snoozeEnabled: Bool = false

        if let n = UIApplication.shared.scheduledLocalNotifications {
            if let result = minFireDateWithIndex(notifications: n) {
                let i = result.1
                snoozeEnabled = alarmModel.alarms[i].snoozeEnabled
            }
        }

        // Specify the notification types.

        let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.sound]
        // Specify the notification actions.
        let stopAction = UIMutableUserNotificationAction()
        stopAction.identifier = Id.stopIdentifier
        stopAction.title = "OK"

        stopAction.activationMode = UIUserNotificationActivationMode.background    // choose activation mode for app on tapping notification

        stopAction.isDestructive = false
        stopAction.isAuthenticationRequired = false

        let snoozeAction = UIMutableUserNotificationAction()
        snoozeAction.identifier = Id.snoozeIdentifier
        snoozeAction.title = "Snooze"
        snoozeAction.activationMode = UIUserNotificationActivationMode.background
        snoozeAction.isDestructive = false
        snoozeAction.isAuthenticationRequired = false

        let actionsArray = snoozeEnabled ? [UIUserNotificationAction](arrayLiteral: snoozeAction, stopAction) : [UIUserNotificationAction](arrayLiteral: stopAction)
        let actionsArrayMinimal = snoozeEnabled ? [UIUserNotificationAction](arrayLiteral: snoozeAction, stopAction) : [UIUserNotificationAction](arrayLiteral: stopAction)
        // Specify the category related to the above actions.
        let alarmCategory = UIMutableUserNotificationCategory()
        alarmCategory.identifier = "myAlarmCategory"
        alarmCategory.setActions(actionsArray, for: .default)
        alarmCategory.setActions(actionsArrayMinimal, for: .minimal)


        let categoriesForSettings = Set(arrayLiteral: alarmCategory)
        // Register the notification settings.
        let newNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: categoriesForSettings)
        UIApplication.shared.registerUserNotificationSettings(newNotificationSettings)
        return newNotificationSettings
    }

Новое редактирование кода:

    func setRouteNotification(_ date: Date, onWeekdaysForNotify weekdays:[Int], snoozeEnabled:Bool,  onSnooze: Bool, soundName: String, routeName: String, index: Int) {
    // Notification content
    let routeCheckNotificationContent = UNMutableNotificationContent()
    let datesForNotification = correctDate(date, onWeekdaysForNotify: weekdays)
    routeCheckNotificationContent.title = "Hello!! Are you ready to cycle?"
    routeCheckNotificationContent.body = "Check route for alerts?"
    routeCheckNotificationContent.categoryIdentifier = Id.notificationCategory
    routeCheckNotificationContent.sound = UNNotificationSound.init(named: soundName + ".mp3") // check for the + ".mp3"

    // Define actions
    let check = UNNotificationAction(identifier: Id.checkActionIdentifier, title: " Check", options: [.foreground])
    let wait = UNNotificationAction(identifier: Id.waitActionIdentifier, title: "Wait", options: [])
    // Define category
    let routeCategory = UNNotificationCategory(identifier: Id.notificationCategory, actions: [check, wait], intentIdentifiers: [], options: [])
    // Register category
    UNUserNotificationCenter.current().setNotificationCategories([routeCategory])


    let repeating: Bool = !weekdays.isEmpty
    routeCheckNotificationContent.userInfo = ["snooze" : snoozeEnabled, "index": index, "soundName": soundName, "routeName": routeName, "repeating" : repeating]
    //repeat weekly if repeat weekdays are selected
    //no repeat with snooze notification
    if !weekdays.isEmpty && !onSnooze{
    }

    syncAlarmModel()
    for d in datesForNotification {
        if onSnooze {
            alarmModel.alarms[index].date = Scheduler.correctSecondComponent(date: alarmModel.alarms[index].date)
        }
        else {
            alarmModel.alarms[index].date = d
        }
        // Notification trigger

        let calendar = Calendar(identifier: .gregorian)


        let components = calendar.dateComponents(in: .current, from: d)
        let newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute, second: components.second, weekday: components.weekday)
        let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)
        // Notification Request
        let routeNotificationRequest = UNNotificationRequest(identifier: "routeNotificationRequest", content: routeCheckNotificationContent, trigger: trigger)

        // Add request
        UNUserNotificationCenter.current().add(routeNotificationRequest) { (Error) in
            if Error != nil {
                print("something went wrong with adding notification")
            }
        }
    }
}

var weekdays: [Int]! - это массив, который заполняется в WeekdaysViewController (TableViewController), выбирая строки.

Теперь, когда я выбираю любой день, уведомление не срабатывает.

Получение данных из формы с помощью JavaScript - краткое руководство
Получение данных из формы с помощью JavaScript - краткое руководство
Получить данные из формы с помощью JS очень просто: вы запрашиваете элемент формы, передаете его конструктору new FormData() и, наконец, получаете...
Пользовательские правила валидации в Laravel
Пользовательские правила валидации в Laravel
Если вы хотите создать свое собственное правило валидации, Laravel предоставляет возможность сделать это. Создайте правило с помощью следующей...
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
0
0
496
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если я правильно понял, вы хотите, чтобы локальное уведомление повторялось. Если это так, вам нужно только настроить свое уведомление с помощью

let dateInfo = Calendar.current.dateComponents([.weekday,.hour,.minute], from: aDateWithTheDayHourAndMinuteYouWantToTriggerTheNotification)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateInfo, repeats: true)
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)

И вуаля

Я просто добавил weekday: components.weekday в мои собственные `` новые компоненты '', и он должен быть им. Я получаю уведомления и действия. Большой. Мне просто нужно попытаться понять, сработают ли повторы в выбранные дни. Я сделаю тест и к вечеру вернусь с результатом. Спасибо.

Vincenzo 10.09.2018 17:01

После модификации, когда я выбираю любой день из уведомления WeekdaysViewController, просто не срабатывает, какие-нибудь идеи?

Vincenzo 14.09.2018 21:12

У меня странное поведение. Уведомление, кажется, не срабатывает в тот день, когда вы его установили, потому что на следующий день .. странно, правда? Вчера я установил уведомление на 00:01 праздника и субботы ... оно сработало. Этим утром я установил один на 7:33 в субботу включительно .. он не сработал ..

Vincenzo 15.09.2018 07:46

Вы можете взглянуть на мои правки? У меня такое странное поведение, которого я действительно не понимаю. Добавив параметр .weekday для повторения, автоматически устанавливает повторение на каждый день? Мог ли мой массив буднего дня противоречить этому?

Vincenzo 15.09.2018 10:46

@ Ахмет Сина Устем. Я видел, как вы редактировали ответ в stackoverflow.com/questions/45061324/…, похоже, это способ решить мою проблему, но я изо всех сил пытаюсь решить ее здесь. Вы видите, где я ошибаюсь?

Vincenzo 15.09.2018 23:20

После модификации, когда я выбираю любой день из уведомления WeekdaysViewController, просто не срабатывает, какие-нибудь идеи? У меня странное поведение. Уведомление, кажется, не срабатывает в тот день, когда вы его установили, но оно срабатывает на следующий день. В пятницу я установил уведомление на 00:01, выбрав пятницу и субботу .. оно сработало в субботу. Этим утром я установил один на 7:33 в субботу включительно ... он не сработал ... Можете ли вы взглянуть на мои правки? Это странное поведение, которого я не понимаю. Мог ли мой массив будних дней конфликтовать с добавленным параметром .weekday?

Vincenzo 15.09.2018 23:24
Ответ принят как подходящий

@Mikael. @Медовый. После некоторой борьбы с кодом, поскольку я думал, что могу использовать только компонент .weekday для установки повторений, я обнаружил, что могу использовать ту же логику настройки уведомления за день повторения с использованием Date, поскольку я сохраняю выбранные даты в массиве , поэтому я установил цикл for in, чтобы установить новое уведомление с уникальным идентификатором для каждой сохраненной даты. Окончательный код:

        func setRouteNotification(_ date: Date, onWeekdaysForNotify weekdays:[Int], snoozeEnabled:Bool,  onSnooze: Bool, soundName: String, routeName: String, index: Int) {
            // Notification content
            let routeCheckNotificationContent = UNMutableNotificationContent()
            let datesForNotification = correctDate(date, onWeekdaysForNotify: weekdays)
            routeCheckNotificationContent.title = "Hello!! Are you ready to cycle?"
            routeCheckNotificationContent.body = "Check route for alerts?"
            routeCheckNotificationContent.categoryIdentifier = Id.notificationCategory
            routeCheckNotificationContent.sound = UNNotificationSound.init(named: soundName + ".mp3") // check for the + ".mp3"

            // Define actions
            let check = UNNotificationAction(identifier: Id.checkActionIdentifier, title: " Check", options: [.foreground])
            let wait = UNNotificationAction(identifier: Id.waitActionIdentifier, title: "Wait", options: [])
            // Define category
            let routeCategory = UNNotificationCategory(identifier: Id.notificationCategory, actions: [check, wait], intentIdentifiers: [], options: [])
            // Register category
            UNUserNotificationCenter.current().setNotificationCategories([routeCategory])


            let repeating: Bool = !weekdays.isEmpty
            routeCheckNotificationContent.userInfo = ["snooze" : snoozeEnabled, "index": index, "soundName": soundName, "routeName": routeName, "repeating" : repeating]
            //repeat weekly if repeat weekdays are selected
            //no repeat with snooze notification
            if !weekdays.isEmpty && !onSnooze{
            }

            syncAlarmModel()
            var counter = 0

            for d in datesForNotification {
                if onSnooze {
                    alarmModel.alarms[index].date = Scheduler.correctSecondComponent(date: alarmModel.alarms[index].date)
                }
                else {
                    alarmModel.alarms[index].date = d
                }
                // Notification trigger

                let calendar = Calendar(identifier: .gregorian)


                let components = calendar.dateComponents(in: .current, from: d)
                var newComponents = DateComponents(calendar: calendar, timeZone: .current, month: components.month, day: components.day, hour: components.hour, minute: components.minute, second: components.second, weekday: components.weekday)
                newComponents.weekday = weekdays[counter]
                let trigger = UNCalendarNotificationTrigger(dateMatching: newComponents, repeats: true)
                // Notification Request
//                let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
                let routeNotificationRequest = UNNotificationRequest(identifier: "routeNotificationRequest\(counter)", content: routeCheckNotificationContent, trigger: trigger)

                // Add request
                UNUserNotificationCenter.current().add(routeNotificationRequest) { (Error) in
                    if Error != nil {
                        print("something went wrong with adding notification")
                    }
                }
                print("added request\(counter)")
                counter = ( counter + 1 )

            }
            print(alarmModel.alarms)
        }

Другие вопросы по теме