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
}
}