Prática 3: Integrando os Componentes Instalados
Assista e acompanhe a prática em sala dos exercícios "Integrando os Componentes Instalados". Execute as instruções conforme a apresentação.
Exercício 1. Integrando o SAMTextView
1.1. Abrir o arquivo Main.Storyboard e localizar o View Controller de Formulário
1.2. Modificar a classe do Text View de Descrição para SAMTextView
1.3. Modificar o Outlet do Text View para corresponder ao novo Tipo
No arquivo ActivityFormViewController.swift modifique o código do Outlet para corresponder ao novo tipo, conforme a listagem abaixo:
@IBOutlet weak var descriptionTextView: UITextView!@IBOutlet weak var descriptionTextView: SAMTextView!
É necessário incluir a referência para a biblioteca SAMTextView no topo do arquivo:
import SAMTextView
1.4. Alterar o Placeholder no método viewDidLoad
Incluir no método viewDidLoad o código para alterar o campo placeholder do SAMTextView:
override func viewDidLoad() { super.viewDidLoad() // Configura os componentes self.descriptionTextView.placeholder = "Descrição detalhada da atividade..." // Código restante do método, não deve ser modificado // ... }
1.5. Execute o App e verifique o placeholder no TextView no Formulário de Atividade
Exercício 2. Integrando o StaticDataTableController
2.1. Abra o arquivo Main.Storyboard e localize o View Controller do Formulário de Atividade
2.2. Criar o Outlet Collection de Células de Repetição
Criar um Outlet Collection para as células de repetição:
- Quantidade de Repetições
- Slider de Quantidade
- Vibração ao Toque
Conforme o código abaixo:
@IBOutlet var repetitionsOptionsCells: [UITableViewCell]!
2.3. Criar o Outlet Colleciton de Células de Tempo Limite
Criar um Outlet Collection para as células de repetição:
- Limite de Tempo
- Slider de Quantidade
Conforme o código abaixo:
@IBOutlet var timeLimitOptionsCells: [UITableViewCell]!
2.4. Alterar a Super Classe do View Controller
Modifique a super classe da class ActivityFormViewController no código:
class ActivityFormViewController: UITableViewController {class ActivityFormViewController: StaticDataTableViewController {
É necessário incluir a referência para a biblioteca StaticDataTableViewController no topo do arquivo:
import StaticDataTableViewController
2.5. Incluir os métodos de apoio
Editar o arquivo ActivityFormViewController.swift para incluir os métodos de apoio abaixo:
/// Esconde ou exibe as células das opções de repetições
func setRepetitionsVisibility(hidden: Bool) {
self.cells(self.repetitionsOptionsCells, setHidden: hidden)
self.reloadDataAnimated(true)
}
/// Esconde ou exibe as células das opções de tempo limite
func setTimeLimitVisibility(hidden: Bool) {
self.cells(self.timeLimitOptionsCells, setHidden: hidden)
self.reloadDataAnimated(true)
}
2.6. Incluir os Action Methods dos UISwitchs
Incluir Action Metidos para o evento Value Changed dos componentes UISwitch conforme o código abaixo:
@IBAction func repetitionsSwitched(sender: UISwitch) {
self.setRepetitionsVisibility(!sender.on)
}
@IBAction func timeLimitSwitched(sender: UISwitch) {
self.setTimeLimitVisibility(!sender.on)
}
2.7. Atualizar o método viewDidLoad para ajustar a exibição dos componentes
Atualizar o método viewDidLoad em ActivityFormViewController.swift de acordo com o código 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.detailsself.repetitionsSwitch.on = (a.repetitions.integerValue > 0)// Carrega e configura as opções de repetições let repetitionsEnabled = (a.repetitions!.integerValue > 0) self.setRepetitionsVisibility(!repetitionsEnabled) self.repetitionsSwitch.on = repetitionsEnabled self.repetitionsSlider.value = a.repetitions.floatValue self.repetitionsLabel.text = a.repetitions.stringValueself.timeLimitSwitch.on = (a.timeLimit.integerValue > 0)// Carrega e configura as opções de tempo limite let timeLimitEnabled = (a.timeLimit!.integerValue > 0) self.setTimeLimitVisibility(!timeLimitEnabled) self.timeLimitSwitch.on = timeLimitEnabled self.timeLimitSlider.value = a.timeLimit.floatValue self.timeLimitLabel.text = self.getTimeDescription(a.timeLimit.integerValue) // 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" } }
2.8. Execute o App e verifique se a marcação/desmarcação dos Switchs esta funcionando adequadamente
Exercício 3. Integrando o EFCircularSlider
3.1. Criar o arquivo TimeLimitChooserViewController.swift no grupo Views
3.2. Incluir o protocolo TimeLimitChooserDelegate
No arquivo criado incluir o protocolo TimeLimitChooserDelegate conforme o código abaixo:
/// Protocolo que deve ser implementado pelo Delegate do Componente
protocol TimeLimitChooserDelegate {
// Informa ao Delegate que o componente mudou a seleção de horas
func timeLimitChooser(chooser: TimeLimitChooserViewController, didChangeTimeLimit seconds: Int)
}
3.3. Incluir a classe TimeLimitChooserViewController
No arquivo criado abaixo do protocolo inserido na tarefa anterior, incluir o código da classe conforme a listagem abaixo:
class TimeLimitChooserViewController : UIViewController {
//
// MARK: - Constants
let baseWidth = CGFloat(320)
let baseHeight = CGFloat(220)
//
// MARK: - Properties
var sliderHours: EFCircularSlider!
var sliderMinutes: EFCircularSlider!
var delegate: TimeLimitChooserDelegate?
}
No topo do arquivo incluir a referência para a biblioteca EFCircularSlider:
import EFCircularSlider
3.4. Incluir o método viewDidLoad
Incluir o método viewDidLoad da classe conforme o código abaixo:
//
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
// Configura a cor de fundo da View de acordo com o Tint Color
self.view.backgroundColor = UINavigationBar.appearance().barTintColor
// Configura o primeiro Slider, de minutos, que será o mais externo
let sliderHourFrame = CGRect(x: 0, y: 0, width: baseWidth, height: baseHeight)
self.sliderHours = EFCircularSlider(frame: sliderHourFrame)
self.sliderHours.unfilledColor = UIColor(red: 23/255.0, green: 47/255.0, blue: 70/255.0, alpha: 1.0)
self.sliderHours.filledColor = self.view.tintColor
self.sliderHours.minimumValue = 0
self.sliderHours.maximumValue = 60
self.sliderHours.lineWidth = 8
self.sliderHours.snapToLabels = false
self.sliderHours.labelFont = UIFont.systemFontOfSize(12.0)
self.sliderHours.labelColor = self.view.tintColor
self.sliderHours.handleType = bigCircle
self.sliderHours.handleColor = self.sliderHours.filledColor
// Esse array determina as marcações ao longo do círculo do slider
let hoursArray = ["5", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "60"]
self.sliderHours.setInnerMarkingLabels(hoursArray)
self.sliderHours.addTarget(self, action:"slidersChanged:", forControlEvents:UIControlEvents.ValueChanged)
self.view.addSubview(self.sliderHours)
// Configura o segundo slider, com so minutos, que será mais interno
let sliderMinutesFrame = CGRectMake(0, 0, 150, 145)
self.sliderMinutes = EFCircularSlider(frame: sliderMinutesFrame)
self.sliderMinutes.unfilledColor = UIColor(red: 23/255.0, green: 47/255.0, blue: 70/255.0, alpha: 1.0)
self.sliderMinutes.filledColor = self.view.tintColor
self.sliderMinutes.minimumValue = 0
self.sliderMinutes.maximumValue = 60
self.sliderMinutes.lineWidth = 8
self.sliderMinutes.labelFont = UIFont.systemFontOfSize(14.0)
self.sliderMinutes.labelColor = self.view.tintColor
self.sliderMinutes.handleType = doubleCircleWithOpenCenter
self.sliderMinutes.handleColor = self.sliderMinutes.filledColor
// Determina as marcações ao longo do círculo do slider
let minutesArray = ["5", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "60"]
self.sliderMinutes.setInnerMarkingLabels(minutesArray)
self.sliderMinutes.addTarget(self, action:"slidersChanged:", forControlEvents: UIControlEvents.ValueChanged)
self.view.addSubview(self.sliderMinutes)
self.sliderMinutes.center = self.sliderHours.center
}
3.5. Incluir o método viewWillLayoutSubviews
Incluir o método viewWillLayoutSubviews conforme a listagem abaixo:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// Re-calcula os frames das Views
self.sliderHours.frame = CGRect(x: (self.view.frame.width / 2) - (self.sliderHours.frame.width / 2),
y: (self.view.frame.height / 2) - (self.sliderHours.frame.height / 2),
width: self.sliderHours.frame.width,
height: self.sliderHours.frame.height)
self.sliderMinutes.center = self.sliderHours.center
}
3.6. Incluir os demais métodos
Incluir os métodos de apoio e Action Methods conforme a listagem abaixo:
//
// MARK: - Métodos de Apoio
func getTimeLimitSeconds() -> Int {
return ((Int(self.sliderHours.currentValue) * 60) + Int(self.sliderMinutes.currentValue)) * 60
}
//
// MARK: - Action Methods
func slidersChanged(slider : EFCircularSlider) {
self.delegate?.timeLimitChooser(self, didChangeTimeLimit: self.getTimeLimitSeconds())
}
3.7. Criar a classe TimeLimitViewCell
Criar a classe TimeLimitViewCell com a super classe UITableViewCell no grupo Views, conforme o código abaixo:
class TimeLimitViewCell: UITableViewCell {
//
// MARK: - Propriedades
var timeLimitChooser: TimeLimitChooserViewController!
var delegate: TimeLimitChooserDelegate? {
didSet {
self.timeLimitChooser.delegate = self.delegate
}
}
//
// MARK: - Initializers
required init?(coder aDecoder: NSCoder) {
self.timeLimitChooser = TimeLimitChooserViewController()
super.init(coder: aDecoder)
}
//
// MARK: - Outros Métodos
override var inputView: UIView {
return self.timeLimitChooser.view
}
override func canBecomeFirstResponder() -> Bool {
return true
}
override func resignFirstResponder() -> Bool {
self.setSelected(false, animated: true)
return super.resignFirstResponder()
}
}
3.8. Configurar a propriedade Class da célula de Tempo Limite
Localizar a célula de tempo limite no Formulário e alterar seu Class para TimeLimitViewCell criado na tarefa anterior.
3.9. Excluir a Célula com o Slider de Tempo Limite
3.10. Excluir as referências para o Slider de Tempo Limite
Exclua as referências para o Slider tempo limite conforme o código abaixo:
Outlet:
@IBOutlet weak var timeLimitSlider: UISlider!
Método viewDidLoad:
self.timeLimitSlider.value = a.timeLimit.floatValue
Método timeLimitValueChanged::
@IBAction func timeLimitValueChanged(sender: UISlider) { self.timeLimitLabel.text = self.getTimeDescription(Int(sender.value)) }
3.11. Incluir a propriedade para armazenar o tempo selecionado
Inclua a propriedade para armazenar o tempo limite selecionado:
var selectedTimeLimit: Int = 0
E atualize o método setActivityData: para utiliza-lo:
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) : 0activity.timeLimit = self.timeLimitSwitch.on ? Int(self.timeLimitSlider.value) : 0activity.timeLimit = self.timeLimitSwitch.on ? self.selectedTimeLimit : 0 }
3.12. Implemente o protocolo TimeLimitChooserDelegate
Atualize a declaração da classe para aderir ao protocolo TimeLimitChooserDelegate:
class ActivityFormViewController: StaticDataTableViewController {class ActivityFormViewController: StaticDataTableViewController, TimeLimitChooserDelegate {
E inclua a implementação de seus métodos:
//
// MARK: - Time Limit Chooser Delegate
func timeLimitChooser(chooser: TimeLimitChooserViewController, didChangeTimeLimit seconds: Int) {
self.selectedTimeLimit = seconds
self.timeLimitLabel.text = self.getTimeDescription(selectedTimeLimit)
}
3.13. Atualize o método tableView:didSelectRowAtIndexPath: para exibir o controle
Atualize o método tableView:didSelectRowAtIndexPath: para apresentar o componente quando a célula de tempo limite for selecionada:
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 (5, 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 } }