Prática 1: Incluindo a Interface para Configurar Notificações
Assista e acompanhe a prática em sala dos exercícios "Incluindo a Interface para Configurar Notificações". Execute as instruções conforme a apresentação.
Exercício 1. Incluindo a Seleção dos Dias da Semana
1.1. Abrir o arquivo Main.Storyboard e localizar o View Controller de Formulário de Atividade
1.2. Duplicar a seção de Repetições
Duplicar a seção de repetições do Table View e posicioná-la abaixo da seção de Limite de Tempo.
1.3. Modificar as propriedades da seção
Modificar as propriedades da seção conforme abaixo:
- Rows: Manter 4
- Header: Lembrete
- Foster: Escolha os dias da semana e o horário em que você deseja ser notificado através da central de notificações de seu dispositivo.
1.4. Modificar os Labels da Seção
Modificar os Labels de acordo:
- Label Medir Repetições modificar para Habilitar Notificação
- Label Quantidade de Repetições modificar para Dias
- Label 100 modificar para Nenhum
1.5. Excluir a terceira célula
1.6. Duplicar a segunda célula
1.7. Modificar os labels da terceira célula
Modificar os Labels de acordo:
- Label Dias para Horário da Notificação
- Label Nenhum para 00:01
1.8. Modificar a propriedade Selection da Segunda e da Terceira Célula para Default
1.9. Reconfigure a quarta célula
Excluas todos os componentes da quarta célula. Altere a propriedade Row Height da célula para 162.
1.10. Desenhe e configure o Date Picker
Desenhe um UIDatePicker centralizado na célula e configure suas constraints para espaçamento 0 em todas as direções. Modifique suas propriedades para:
- Mode: Time
- Interval: 1 minute
- Date: Current Date
Exercício 2. Acrescentando as Funcionalidades da Interface
2.1. Abrir o arquivo Main.Storyboard e localizar o View Controller de Formulário de Atividade
2.2. Crie os Outlets para os componentes desenhados
Crie os Outlets para os novos componentes conforme o código abaixo:
@IBOutlet weak var remindersSwitch: UISwitch!
@IBOutlet weak var reminderDaysLabel: UILabel!
@IBOutlet weak var reminderTimePickerCell: UITableViewCell!
@IBOutlet weak var reminderTimeLabel: UILabel!
@IBOutlet weak var reminderTimePicker: UIDatePicker!
2.3. Crie o Outlet Collection para as Células da Seção de Lembretes
Crie o Outlet Collection para as 3 últimas células da seção de reminders conforme o código abaixo:
@IBOutlet var remindersOptionsCells: [UITableViewCell]!
2.4. Adicione o método para ajustar a visibilidade das células
Abaixo do método setTimeLimitVisibility: inclua o método abaixo:
/// Esconde ou exibe as células das opções de lembretes
func setRemindersVisibility(hidden: Bool) {
self.cells(self.remindersOptionsCells, setHidden: hidden)
if hidden {
self.cell(self.reminderTimePickerCell, setHidden: hidden)
}
self.reloadDataAnimated(true)
}
2.5. Inclua o Action Method para o Switch de Lembretes
Inclua o Action Method para o Switch de Lembretes conforme o código abaixo:
@IBAction func remindersSwitched(sender: UISwitch) {
self.setRemindersVisibility(!sender.on)
}
2.6. Atualize o Código do Método tableView:didSelectRowAtIndexPath:
Atualize o código do método conforme o código abaixo:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { let indexPathT = (indexPath.section, indexPath.row) switch indexPathT { case (3, 1): let cell = tableView.cellForRowAtIndexPath(indexPath) as TimeLimitViewCell cell.delegate = self cell.becomeFirstResponder() case (4, 2): let hidden = !self.cellIsHidden(self.reminderTimePickerCell) self.cell(self.reminderTimePickerCell, setHidden: hidden) self.reloadDataAnimated(true)case (5, 0):case (6, 0): let alert = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) alert.addAction(UIAlertAction(title: "Apagar Atividade", style: .Destructive) { (action) in TraqtDataContext.sharedInstance.activities.delete(self.activity!.activityId) self.navigationController?.popViewControllerAnimated(true) }) alert.addAction(UIAlertAction(title: "Cancelar", style: .Cancel, handler: nil)) self.tableView.deselectRowAtIndexPath(indexPath, animated: true) self.presentViewController(alert, animated: true, completion: nil) default: break } }
2.7. Atualize o Código do Método viewDidLoad
Atualize o método
override func viewDidLoad() { // Código existente anteriormente, não modifique // ... // Configura a exibição e as animações da célula self.insertTableViewRowAnimation = .Middle self.deleteTableViewRowAnimation = .Middle self.reloadTableViewRowAnimation = .Middle self.cell(self.reminderTimePickerCell, setHidden: true) self.reloadDataAnimated(false) }
2.8. Inclua o Método de Apoio para formatação da data selecionada
Inclua o método de apoio abaixo:
/// Configura o Label com o horário formatado de acordo com a seleção do Date Picker
func setReminderTime() {
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
self.reminderTimeLabel.text = dateFormatter.stringFromDate(self.reminderTimePicker.date)
}
2.9. Inclua o Action Method do Date Picker
Inclua o Action Method para o evento Value Changed do Date Picker:
@IBAction func remindersValueChanged(sender: UIDatePicker) {
self.setReminderTime()
}
Exercício 3: Incluindo o View Controller para a Seleção de Dias da Semana
3.1. Abrir o arquivo Main.Storyboard e Desenhar um Table View Controller Próximo ao formulário de Atividades
3.2. Embutir o View Controller dentro de um Navigation Controller
3.3. Configurar o View Controller
Alterar o título do View Controller Dias da Semana. Incluir dois UIBarButtonItem's na barra de navegação, sendo o da esquerda com o Identifier Cancel e o da direita com o Identifier Done.
3.4. Configurar a Célula de Proptótipo
Configurar a célula de protótipo com o o Identifier WeekDayCell e o tipo Basic.
3.5. Criar um Segue entre a célula Dias e o Navigation Controller
Criar um Segue do tipo Present Modally entre a célula Dias do formulário e o Navigation Controller, configurar seu Identifier para PickReminderDays.
3.6. Configurar a célula de Dias
Configurar a célula de dias com a propriedade Selection para Default e Accessory para Disclosure Indicator. Configurar a propriedade Constant da Constraint Trailing Space to: Superview Equals: 15 para 0.
3.7. Inserir os fontes de modelo dentro da pasta model
Baixe os arquivos adicionais de modelo a partir deste link. Insira-os no grupo model do projeto.
3.8. Criar a classe WeekDaysPickerController como subclasse de UITableViewController
3.9. Configurar o Table View para corresponder a nova classe
3.10. Declarar um novo protocolo para Delegate do Picker de dias da semana
No início do arquivo WeekDaysPickerController da classe criada incluir o código para o protocolo do Delegate desta classe (acima da declaraçãod a classe):
/// Protocolo usado pelo delegate do componente WeekDaysPickerController
protocol WeekDaysPickerControllerDelegate {
/**
Informa o delegate que o usuário concluiu a seleção dos dias da semana.
- parameter controller: Uma referência para o Controller que realizou a operação.
- parameter weekdays: Uma instância com os dias da semana selecionados pelo usuário.
*/
func weekDaysPicker(controller: WeekDaysPickerController, didPickWeekDays weekdays: WeekDays)
/**
Informa o delegate que o usuário cancelou a seleção dos dias da semana.
- parameter controller: Uma referência para o Controller que realizou a operação.
*/
func weekDaysPickerDidCancel(controller: WeekDaysPickerController)
}
3.11. Inclua as propriedades da Classe WeekDaysPickerController
Inclua as propriedades conforme o código abaixo:
//
// MARK: - Properties
var delegate: WeekDaysPickerControllerDelegate?
var selectedWeekDays: WeekDays = .None
var weekDays: [WeekDays.WeekDayInfo]!
3.12. Altere o método viewDidLoad da Classe WeekDaysPickerController
Altere o método viewDidLoad conforme o código abaixo:
//
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
self.weekDays = selectedWeekDays.asWeekDays()
}
3.13. Configure o Data Source do Table View
Configure o Data Source do Table View alterando os métodos do protocolo conforme o código abaixo:
// // MARK: - Table view data sourceoverride func numberOfSectionsInTableView(tableView: UITableView) -> Int { // #warning Potentially incomplete method implementation. // Return the number of sections. return 0 }override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return weekDays.count }
3.14. Configure o Delegate do Table View
Configure o Delegate do Table View alterando os métodos do protocolo conforme o código abaixo:
//
// MARK: - Table View Delegate
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
let weekDay = weekDays[indexPath.row]
cell.accessoryType = weekDay.selected ? .Checkmark : .None
cell.textLabel!.text = weekDay.longName
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedCell = tableView.cellForRowAtIndexPath(indexPath)
if selectedCell?.accessoryType == UITableViewCellAccessoryType.Checkmark {
selectedCell?.accessoryType = .None
self.weekDays[indexPath.row].selected = false
self.selectedWeekDays.remove(weekDays[indexPath.row].weekDaysValue!)
} else {
selectedCell?.accessoryType = .Checkmark
self.weekDays[indexPath.row].selected = true
self.selectedWeekDays.insert(weekDays[indexPath.row].weekDaysValue!)
}
selectedCell?.setSelected(false, animated: true)
}
3.15. Inclua os Action Methods dos Botões da Barra de Navegação
Inclua os Action Methods dos botões Done e Cancel conforme o código abaixo:
//
// MARK: - Action Methods
@IBAction func doneTapped(sender: UIBarButtonItem) {
self.delegate?.weekDaysPicker(self, didPickWeekDays: self.selectedWeekDays)
}
@IBAction func cancelTapped(sender: UIBarButtonItem) {
self.delegate?.weekDaysPickerDidCancel(self)
}
3.16. Inclua a propriedade de dia selecionado no arquivo ActiviftFormViewController
Inclua a seguinte propriedade no arquivo ActiviftFormViewController.swift:
var reminderWeekDays: WeekDays = .None
3.17. Inclua o método de apoio para mostrar os dias da semana selecionados
Inclua o método abaixo na seção de métodos de apoio:
/// Configura o Label de dias da semana com a descrição conforme a seleção atual
func setReminderDaysLabel() {
self.reminderDaysLabel.text = self.reminderWeekDays.toString()
}
3.18. Torne a classe ActivityFormViewController aderente ao protocolo WeekDaysPickerControllerDelegate
Atualize a declaração da classe ActivityFormViewController para incluir o delegate do Week Days Picker:
class ActivityFormViewController: StaticDataTableViewController, TimeLimitChooserDelegate {class ActivityFormViewController: StaticDataTableViewController, TimeLimitChooserDelegate, WeekDaysPickerControllerDelegate {
3.19. Implemente os métodos do delegate
Implemente os métodos do delegate conforme o código abaixo:
//
// MARK: - WeekDaysPickerControllerDelegate
func weekDaysPicker(controller: WeekDaysPickerController, didPickWeekDays weekdays: WeekDays) {
self.reminderWeekDays = weekdays
self.setReminderDaysLabel()
self.dismissViewControllerAnimated(true, completion: nil)
}
func weekDaysPickerDidCancel(controller: WeekDaysPickerController) {
self.dismissViewControllerAnimated(true, completion: nil)
}
3.20. Atualize o método prepareForSegue:sender:
Atualize o código do método prepareForSegue:sender: conforme a listagem abaixo:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "PickReminderDays" { let nvc = segue.destinationViewController as! UINavigationController let vc = nvc.topViewController as! WeekDaysPickerController vc.delegate = self } if let destVC = segue.destinationViewController as? SessionHistoryTableViewController { destVC.activity = self.activity } }
3.21. Execute o App e verifique a tela de seleção de dias da semana
Exercício 4. Carregando e Persistindo as Configurações de Lembrete
4.1. Obtenha a pasta Extensions e insira a pasta no Traqt do projeto
Baixa a pasta com os códigos fontes de extensões adicionais do Swift a partir deste link. Inclua a pasta como um novo grupo no projeto Traqt.
4.2. Atualize o método viewDidLoad da class ActivityFormViewController para carregar as informações de lembrete
Atualize o método viewDidLoad conforme a listagem abaixo:
override func viewDidLoad() { super.viewDidLoad() // Configura os componentes self.descriptionTextView.placeholder = "Descrição detalhada da atividade..." // Do any additional setup after loading the view. if let a = self.activity { self.title = "Editar Atividade" self.nameTextField.text = a.name self.descriptionTextView.text = a.details // Carrega e confgiura as opções de repetições var repetitionsEnabled = (a.repetitions.integerValue > 0) self.setRepetitionsVisibility(!repetitionsEnabled) self.repetitionsSwitch.on = repetitionsEnabled self.repetitionsSlider.value = a.repetitions.floatValue self.repetitionsLabel.text = a.repetitions.stringValue // Carrega e configura as opções de tempo limite var timeLimitEnabled = (a.timeLimit.integerValue > 0) self.setTimeLimitVisibility(!timeLimitEnabled) self.selectedTimeLimit = a.timeLimit.integerValue self.timeLimitSwitch.on = timeLimitEnabled self.timeLimitLabel.text = self.getTimeDescription(a.timeLimit.integerValue) // Configura as propriedades do Reminders let remindersEnabled = a.reminders!.boolValue self.setRemindersVisibility(!remindersEnabled) self.remindersSwitch.on = remindersEnabled self.reminderTimePicker.date = a.reminderTime!.integerValue.timeIntToDate()! if let reminderDays = a.reminderDays?.integerValue { self.reminderWeekDays = WeekDays(rawValue: reminderDays) } self.setReminderDaysLabel() self.setReminderTime() // Quantidade de sessões dessa atividade let sessions = a.sessions.count if sessions > 0 { self.historyLabel.text = "\(sessions) " + ((sessions == 1) ? "Sessão" : "Sessões") } } else { self.title = "Nova Atividade" } // Configura a exibição e as animações da célula self.insertTableViewRowAnimation = .Middle self.deleteTableViewRowAnimation = .Middle self.reloadTableViewRowAnimation = .Middle self.cell(self.reminderTimePickerCell, setHidden: true) self.reloadDataAnimated(false) }
4.3. Atualizar o Método setActivityData:
Atualize o método setActivityData: conforme a listagem abaixo:
func setActivityData(activity: Activity) { activity.name = self.nameTextField.text activity.details = self.descriptionTextView.text activity.enableVibration = self.vibrateSwitch.on activity.repetitions = self.repetitionsSwitch.on ? Int(self.repetitionsSlider.value) : 0 activity.timeLimit = self.timeLimitSwitch.on ? self.selectedTimeLimit : 0 activity.reminders = self.remindersSwitch.on activity.reminderTime = self.reminderTimePicker.date.toIntTime() activity.reminderDays = self.reminderWeekDays.rawValue }
4.4. Atualizar o Método prepareForSegue:sender:
Atualize o método prepareForSegue:sender: para repassar a informação dos dias selecionados conforme a listagem abaixo:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "PickReminderDays" { let nvc = segue.destinationViewController as UINavigationController let vc = nvc.topViewController as WeekDaysPickerController vc.delegate = self vc.selectedWeekDays = self.reminderWeekDays } if let destVC = segue.destinationViewController as? SessionHistoryTableViewController { destVC.activity = self.activity } }