Prática 1: Melhorias de Usabilidade
Assista e acompanhe a prática em sala dos exercícios "Melhorias de Usabilidade". Execute as instruções conforme a apresentação.
Exercício 1. Abstraindo o View Controller de Atividades
1.1. Criar a Classe ActivitiesViewController herdando de SwiftyIOTableViewController no grupo ViewControllers
1.2. Substitua a Implementaçnao da classe ActivitiesViewController
Substitua a Implementaçnao da classe ActivitiesViewController com o código abaixo:
class ActivitiesViewController: CoreDataTableViewController { override func viewDidLoad() { super.viewDidLoad()// Do any additional setup after loading the view.// Carrega as atividades pelo Fetched Results Controller self.fetchedResultsController = TraqtDataContext.sharedInstance.activities.getFetchedResultsController(sortDescriptors: NSSortDescriptor(key: "name", ascending: true)) } }
1.3. Inclua uma constante para o Identitiy da Célula de protótipo
No início do arquivo ActivitiesViewController.swift inclua o código abaixo:
/// Identifier para a célula de atividade
let kActivityCell = "ActivityCell"
1.4. Inclua uma seção de métodos de Apoio
Inclua uma seção de métodos de Apoio usando o código da listagem abaixo:
//
// MARK: - Métodos de Apoio
func getActivityAtIndexPath(indexPath: NSIndexPath) -> Activity {
let activity = self.fetchedResultsController?.objectAtIndexPath(indexPath) as Activity
return activity
}
1.5. Inclua uma seção de Overridables
Inclua o código abaixo para criar uma seção de overridables:
//
// MARK: - Overridables
/**
Chamado depois que o usuário seleciona uma atividade na listagem.
Esse método deve ser sobrescrito pela classe concreta para que ele implemente a funcionalidade desejada quando o usuário selecionar uma atividade.
:param: activity Atividade selecionada.
*/
func selectedActivity(activity: Activity) {
//
// Esse método deve ser sobrescrito pela classe concreta para incluir a funcionalidade desejada quando o usuário selecionar uma atividade
}
1.6. Inclua os Métodos do Datasource e do Delegate do Table View
Inclua os Métodos do Datasource e do Delegate do Table View Controller conforme o código da listagem abaixo:
//
// MARK: - Table View Data Source/Delegate
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Tenta obter a célula, se não existir cria uma nova instância
var cell = tableView.dequeueReusableCellWithIdentifier(kActivityCell) as UITableViewCell!
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: kActivityCell)
}
// Configura a célula
let activity = self.getActivityAtIndexPath(indexPath)
cell.textLabel?.text = activity.name
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Executa a ação especificada pelo
let activity = self.getActivityAtIndexPath(indexPath)
self.selectedActivity(activity)
}
1.7. Criar a classe ConfigActivitiesViewController herdando de ActivitiesViewController no grupo ViewControllers
1.8. Substituir a implementação da classe
Substitua a implementação padrão da classe pelo código abaixo:
class ConfigActivitiesViewController: ActivitiesViewController {
//
// MARK: - Navegação
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "EditActivity" {
let destVC = segue.destinationViewController as! ActivityFormViewController
let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell)!
let activity = self.getActivityAtIndexPath(indexPath)
destVC.activity = activity
}
}
}
1.9. Localize o View Controller de Atividades e Atualize a sua referência de classe para ConfigActivitiesViewController
Exercício 2. Melhorando a Tela de Início
2.1. Abra o arquivo Main.Storyboard e desenhe um Table View Controller próximo ao View Controller de Início
2.2. Insira o novo View Controller em um Navigation Controller
2.3. Criar a classe SelectActivityViewController herdando de ActivitiesViewController no grupo ViewControllers
2.4. Inclua um protocolo para o delegate do View Controller
Inclua o código abaixo para declarar um protocolo de delegate do View Controller:
protocol SelectActivityControllerDelegate {
/**
Chamado quando o usuário seleciona uma atividade.
:param: controller O View Controller que disparou a ação.
:param: activity A atividade selecionada pelo usuário.
*/
func selectActivityController(controller: SelectActivityViewController, didSelectActivity activity: Activity)
}
2.5. Substitua a implementação da classe
Substitua a implementação padrão da classe pelo código abaixo:
SelectActivityViewController: ActivitiesViewController {
//
// MARK: - Properties
var delegate: SelectActivityControllerDelegate?
//
// MARK: - Overrides
override func selectedActivity(activity: Activity) {
self.delegate?.selectActivityController(self, didSelectActivity: activity)
}
}
2.6. Localize o View Controller de Atividades e Atualize a sua referência de classe para SelectActivityViewController
2.7. Atualize o título do View Controller para Selecionar a Atividade
2.8. Exclua o Picker View de seleção de atividade
2.9. Inclua a Constraint Vertical Align in Container no Controle de Início da Sessão
2.10. Desenhe um UIButton para seleção da atividade
Desenhe um Button para seleção da atividade abaixo do botão de início da sessão, com o frame (16, 407, 568, 80), e inclua as constraints:
- Leading Space to: Superview - Equals: 16
- Trailing Space to: Superview - Equals: 16
- Top Space to: Long Press button - Equals: 8
- Height Equals: 80
Configure as propriedades do botão para:
- Text: Escolha sua Atividade
- Font: System 20.0
2.11. Crie um Segue para a tela de seleção
Crie um Segue a partir do botão criado anteriormente com o tipo Present Modally e com o Identifier SelectActivity.
2.12. Crie um Outlet para o botão
Crie um Outlet para o botão conforme o código abaixo:
@IBOutlet weak var selectActivityButton: UIButton!
2.13. Remova o Outlet do Picker View
Remova o Outlet do Picker View conforme o código abaixo:
@IBOutlet weak var activitiesPickerView: UIPickerView!
2.14. Atualize as propriedades
Atualize as propriedades da classe conforme o código abaixo:
lazy var activities: [Activity] = TraqtDataContext.sharedInstance.activities.getAll()lazyvar selectedActivity: Activity?= self.activities.first
2.15. Remova o método viewWillAppear
Remova o método viewWillAppear conforme o código abaixo:
override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) // Mantém o picker view sincronziado com o banco de dados do Core Data sempre que ela é exibida self.activities = TraqtDataContext.sharedInstance.activities.getAll() self.activitiesPickerView.reloadAllComponents() }
2.16. Remova o Picker View Delegate e Data Source
Remova os métodos do UIPickerViewDelegate e UIPickerViewDataSource conforme a listagem abaixo:
// // MARK: - UIPickerViewDataSource func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { return 1 } func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return self.activities.count } // // MARK: - UIPickerViewDelegate func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { self.selectedActivity = self.activities[row] } func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { return self.activities[row].name }
2.17. Atualize a declaração da classe
Atualize a declaração da classe NewSessionViewController conforme o código abaixo:
class NewSessionViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {class NewSessionViewController: UIViewController, SelectActivityControllerDelegate {
2.18. Inclua a implementação do protocolo do Delegate
Inclua a implementação do protocolo do delegasse no final da classe conforme o código abaixo:
//
// MARK: - SelectActivityControllerDelegate
func selectActivityController(controller: SelectActivityViewController, didSelectActivity activity: Activity) {
// Carrega a atividade e atualiza o título do botão
self.selectedActivity = activity
self.selectActivityButton.setTitle(activity.name, forState: .Normal)
// Fecha o View Controller de Seleção
self.dismissViewControllerAnimated(true, completion: nil)
}
2.19. Atualize o método prepareForSegue:sender:
Atualize o método prepareForSegue:sender: conforme o código abaixo:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "StartSession" {
let destVC = segue.destinationViewController as SessionViewController
destVC.activity = self.selectedActivity
}<strong> else if segue.identifier == "SelectActivity" {
let nvc = segue.destinationViewController as! UINavigationController
let destVC = nvc.topViewController as! SelectActivityViewController
destVC.delegate = self
}</strong>
}
2.20. Atualize o Action Method do botão iniciar sessão
Atualize o código do Action Method do botão iniciar sessão conforme o código abaixo:
@IBAction func startSession(sender: LongPressButton) {
if let a = self.selectedActivity {
self.performSegueWithIdentifier("StartSession", sender: self)
} else {
<strong>self.selectActivityButton.setTitle("Oi! Antes escolha sua atividade", forState: .Normal)</strong>
<del>// Se não tiver selecionado nenhuma atividade apresenta uma mensagem
let alertC = UIAlertController(title: "Traqt", message: "Selecione uma atividade para iniciar.", preferredStyle: UIAlertControllerStyle.Alert)
alertC.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Cancel, handler: nil))
self.presentViewController(alertC, animated: true, completion: nil)</del>
}
sender.pressHandled()
}
Exercício 3. Incluindo a barra de título na tela inicial
3.1. Criar um grupo Assets no projeto abaixo do grupo Traqt
3.2. Baixar o arquivo Fonts.zip descomprimir e copiar para dentro do grupo Assets
Baixe o arquivo com as Fonte personalizada do Traqt a partir deste link e e copie para dentro do grupo Assets.
3.3. Incluir a referência para a fonte no arquivo de configuração
Abra o arquivo Info.plist, adicione ou localize a chave Fonts provided by the application, adicione um novo item com o nome Tecno-Trance.otf.
3.4. Desenhar o Label de Título no View Controller de Início
Desenhe um novo Label no View Controller de Início e ajuste o frame para (0, 0, 600, 120), e inclua as constriants:
- Height Equals: 120
- Leading Space to: Superview - Equals 0
- Top Space to: Superview - Equals 0
- Trailing Space to: Superview - Equals 0
Ajuste as propriedades do Label para:
- Text: Traqt
- Color: White Color
- Font: TecnoTrance-Regular 82.0
- Alignment: Center
- Background: #357EAA
Exercício 4. Incluindo a Busca na Listagem de Atividades
4.1. Abra o arquivo ActivitiesViewController e atualize suas propriedades
Atualize as propriedades do arquivo conforme o código abaixo:
//
// MARK: - Properties
var filteredActivities = [Activity]()
4.2. Atualize o método tableView:numberOfRowsInSection
Atualize o método tableView:numberOfRowsInSection conforme a listagem abaixo:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.searchDisplayController!.searchResultsTableView {
return self.filteredActivities.count
} else {
return super.tableView(tableView, numberOfRowsInSection: section)
}
}
4.3. Atualize o método tableView:cellForRowAtIndexPath:
Atualize o método tableView:cellForRowAtIndexPath: conforme a listagem abaixo:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Tenta obter a célula, se não existir cria uma nova instância
var cell = tableView.dequeueReusableCellWithIdentifier(kActivityCell)
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: kActivityCell)
}
// Configura a célula
<del>let activity = self.getActivityAtIndexPath(indexPath)</del>
<strong>var activity: Activity
if tableView == self.searchDisplayController!.searchResultsTableView {
activity = self.filteredActivities[indexPath.row]
} else {
activity = self.getActivityAtIndexPath(indexPath)
}</strong>
cell.textLabel.text = activity.name
return cell
}
4.4. Atualize o método tableView:didSelectRowAtIndexPath:
Atualize o método tableView:didSelectRowAtIndexPath: conforme a listagem abaixo:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Executa a ação especificada pelo
var activity: Activity
if tableView == self.searchDisplayController!.searchResultsTableView {
activity = self.filteredActivities[indexPath.row]
} else {
activity = self.getActivityAtIndexPath(indexPath)
}
self.selectedActivity(activity)
}
4.5. Adicione o Método de Apoio
Adicione o método da listagem abaixo na seção de métodos de apoio:
func filterContentForSearchText(searchText: String?) {
if let searchText = searchText {
let predicate = NSPredicate(format: "name CONTAINS[cd] %@", searchText)
self.filteredActivities = TraqtDataContext.sharedInstance.activities.filter(predicate, sortDescriptors: [ NSSortDescriptor(key: "name", ascending: true) ])!
}
}
4.6. Atualize a declaração da classe
Atualize a declaração da classe ActivitiesViewController conforme a listagem abaixo, substitua:
class ActivitiesViewController: SwiftyIOTableViewController {
Por:
class ActivitiesViewController: SwiftyIOTableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
4.7. Inclui os métodos dos protocolos acrescentando
Inclua os métodos dos protocolos acrescentando na declaração da classe, conforme a listagem abaixo:
//
// MARK: - UISearchBarDelegate
func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String?) -> Bool {
self.filterContentForSearchText(searchString)
return true
}
func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchScope searchOption: Int) -> Bool {
self.filterContentForSearchText(self.searchDisplayController?.searchBar.text)
return true
}
4.8. Desenhe um Search Bar and Search Display dentro do Table View de Atividades e de Seleção de Atividades e atualize suas propriedades
Desenhe um componente Search Bar and Search Display dentro do Table View de Atividades e dentro do Table View de Seleção de Atividades. Selecione e configure as propriedades conforme abaixo:
- Placeholder: Procurar Atividade