Prática 2: Configurando o Envio de Notificações

Assista e acompanhe a prática em sala dos exercícios "Configurando o Envio de Notificações". Execute as instruções conforme a apresentação.

Exercício 1. Solicitando Autorização para o Envio de Notificações

1.1. Registrar o uso de Notificações de Locais

Abra o arquivo AppDelegate.swift e no método application:didFinishLaunchingWithOptions: e inclui o código abaixo antes da instrução return true:

// Habilita as notificações locais
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil))

Exercício 2. Configurando as Notificações de Acordo com as Seleções do Usuário

2.1. Criar uma Extension da classe Activity para Reminders

Crie um arquivo do tipo Swift File com o nome Activity+Reminders.swift no grupo Model.

2.2. Inclua o código da Extensão

Inclua o código da extensão no arquivo criado:

import UIKit

extension Activity {

    //
    // MARK: - Properties

    var reminderWeekDays: WeekDays {
        get {
            if let wd = self.reminderDays?.integerValue {
                return WeekDays(rawValue: wd)
            }
            return WeekDays.None
        }
        set {
            self.reminderDays = newValue.rawValue
        }
    }

    //
    // MARK: - Métodos para Gerenciamento das Notificações Locais

    /// Agenda as notificações locais para esta atividade
    func scheduleLocalNotifications() {
        Activity.scheduleLocalNotifications(forActivity: self)
    }

    /**
        Agenda as notificaçõs locais de uma atividade.

        - parameter activity: Atividade para a qual deseja agendar as notificações.
     */
    class func scheduleLocalNotifications(forActivity activity: Activity) {
        // Check if reminders are enabled
        if !activity.reminders!.boolValue {
            return
        }

        // Adiciona recorrencia de notificações locais no horário especificado
        let reminderTime = activity.reminderTime!.integerValue
        if reminderTime >= Int.TIME_MIN && reminderTime <= Int.TIME_MAX {
            let alertBody = "Não se esqueça de sua atividade \"\(activity.name)\"!"
            if activity.reminderWeekDays.contains(.Sunday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Sunday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
            if activity.reminderWeekDays.contains(.Monday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Monday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
            if activity.reminderWeekDays.contains(.Tuesday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Tuesday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
            if activity.reminderWeekDays.contains(.Wednesday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Wednesday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
            if activity.reminderWeekDays.contains(.Thursday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Thursday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
            if activity.reminderWeekDays.contains(.Friday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Friday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
            if activity.reminderWeekDays.contains(.Saturday) {
                scheduleWeeklyLocalNotification(reminderTime, weekDay: .Saturday, withBody: alertBody, identifiedBy: activity.activityId!)
            }
        }
    }

    /**
        Agenda uma notificação para ser disparada semanalmente no dia semana especificado.

        - parameter reminderTime: A representação em formato Int do horário que a notificação deve ser disparada.
        - parameter body: O corpo da notificação.
        - parameter key: Uma chave para identificar a notificação no sistema.
     */
    class func scheduleWeeklyLocalNotification(reminderTime: Int, weekDay: WeekDay, withBody body: String, identifiedBy key: String) {
        if let baseDate = NSDate().getNextDate(forWeekDay: weekDay) {
            let fireDate = reminderTime.timeIntToDate(baseDate)!
            let notification = UILocalNotification()
            notification.fireDate = fireDate
            notification.alertBody = body
            notification.soundName = UILocalNotificationDefaultSoundName
            notification.repeatInterval = NSCalendarUnit.WeekOfMonth
            notification.applicationIconBadgeNumber = 1
            notification.userInfo = [ "NotificationKey": key ]

            UIApplication.sharedApplication().scheduleLocalNotification(notification)
        }
    }

}

2.3. Inclua o método para remover as notificações de uma atividade

Inclua o método de apoio para remover as notificações de uma atividade no final da classe:

/**
    Remove todas as notificações agendadas para uma determinada atividade.

    - parameter id: O ID da atividade para qual deseja excluir as notificações.
 */
class func clearNotificationsOfActivity(id: String) {
    var notificationsToCancel = [UILocalNotification]()
    if let notifications = UIApplication.sharedApplication().scheduledLocalNotifications {
        for notification in notifications {
            if let userInfo = notification.userInfo {
                if let notificationId = userInfo["NotificationKey"] as? NSString {
                    if notificationId == id {
                        notificationsToCancel.append(notification)
                    }
                }
            }
        }
    }

    for notification in notificationsToCancel {
        UIApplication.sharedApplication().cancelLocalNotification(notification)
    }
}

2.4. Inclua o override para tratar do evento salvar do NSManagedObject

Inclua o código abaixo para tratar o evento em que a instância de um objeto Activity é persistida:

//
// MARK: - Overrides

override func didSave() {
    super.didSave()

    // Remove as notificações agendadas anteriormente
    Activity.clearNotificationsOfActivity(self.activityId!)

    // Verifica se o registro da atividade não esta sendo excluido, nesse caso o usuário não desejará mais receber notificação alguma
    if !deleted {
        scheduleLocalNotifications()
    }
}

2.5. Inclua o método para limpar os Badges

No arquivo AppDelegate.swift inclua o método para tratar o evento applicationDidBecomeActive para limpar os badges do App:

func applicationDidBecomeActive(application: UIApplication) {
    application.applicationIconBadgeNumber = 0      // Limpa os Badges das notificações locais
}

2.6. Execute o App e verifique se as notificações estão sendo geradas para os lembretes salvos