Prática 2: Criando as telas de Sessão

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

Exercício 1: Criando a Tela de Início

1.1. Crie um Grupo para os ViewControllers

Crie um grupo para armazenar os arquivos referentes a View Controllers com o nome ViewControllers.

1.2. Crie a classe NewSessionViewController usando o template Cocoa Touch Class

A classe deve ficar dentro do grupo ViewControllers e deve herdar de UIViewController.

1.3. Associe a classe ao View Controller no Storyboard

No arquivo Main.storyboard localize o View Controller principal e modifique sua classe para NewSessionViewController no Identity Inspector.

1.4. Execute o App e verifique se é apresentada uma tela em branco


Exercício 2: Desenhando a Tela de Início

2.1. Desenhe um UIPickerView centralizado na tela

2.2. Desenhe um UIButton abaixo do Picker View

Desenhe um UIButton abaixo do Picker View e altere seu título para Iniciar Atividade.

2.3. Execute o App no simulador do iPhone 5 e verifique que o layout é apresentado de maneira incorreta


Exercício 3: Ajustando o Layout do App

3.1. Adicione constraints para centralizar verticalmente o UIPickerView

3.2. Adicione constraints para alinhar o UIPickerView com as bordas esquerda e direita do View Controller (respeitando as margens)

3.3. Teste as constraints aplicadas

4.4. Adicione constraints ao UIButton para que seu Centro X fique alinhado com o Centro X do Picker View, e mantendo o espaçamento vertical padrão

5.5. Teste as constraints aplicadas


Exercício 4: Alimentando o Picker View

4.1. Inclua as propriedades no View Controller de Nova Sessão

No arquivo NewSessionViewController.swift inclua uma nova sessão de propriedades conforme o código abaixo:

//
// MARK: - Propriedades

lazy var activities: [Activity] = TraqtDataContext.sharedInstance.activities.getAll()
lazy var selectedActivity: Activity? = self.activities.first

//
// MARK: - View Lifecycle

4.2. Torne o View Controller aderente aos protocolos do Picker View

No arquivo NewSessionViewController.swift modifique a declaração da classe para incluir os protocolos conforme o código abaixo:

class NewSessionViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {

4.3. Inclua o código do delegate e data source do Picker View

No arquivo NewSessionViewController.swift inclua o código 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
}

4.4. Associe o View Controller como Data Source e Delegate do Picker View

No arquivo Main.storyboad localize o View Controller de início, selecione o Picker View e crie uma associação com o View Controller para torna-lo delegate e dataSource do Picker View.

4.5. Execute e teste as alterações


Exercício 5: Re-criando o View Controller de Sessão

5.1. Crie a classe SessionViewController usando o template Cocoa Touch Class

A classe deve ficar dentro do grupo ViewControllers e deve herdar de UIViewController.

5.2. Adicione um View Controller ao Storyboard

No arquivo Main.Storyboard acrescente um novo View Controller a partir do Object Library, posicionado ao lado do View Controller de início.

5.3. Associe a classe ao View Controller no Storyboard

No arquivo Main.storyboard localize o novo View Controller e modifique sua classe para SessionViewController no Identity Inspector.

5.4. Modifique a cor de fundo do View Controller de Sessão para Black Color

5.5. Adicione a barra de título ao View Controller de Sessão

No arquivo Main.storyboard localize o View Controller de Sessão e arraste um Label para dentro dele. Modifique suas dimensões conforme a tabela abaixo:

Propriedade Valor
X 0
Y 0
Width 600
Height 80

Adicione as Constraints para que o botão fique alinhando com o topo, as laterais esquerda e direita, e mantenha uma altura fixa de 80 pontos.

Modifique as propriedades do Label conforme a tabela abaixo:

Propriedade Valor
Color White
Alignment Center
Background #357EAA
Font Headline
Text Plain - [Atividade]

6. Adicione o Label do Cronometro

No arquivo Main.Storyboard localize o View Controller de Sessão e arraste um Label alinhado com o centro do View Controller. Adicione Constraints para manter o label centralizado na tela com 40 pontos acima do centro vertical.

Modifique as propriedades do Label conforme a tabela abaixo:

Propriedade Valor
Font System Bold 24.0
Text Plain - 00:00:00

5.7. Adicione o Label de Repetições

No arquivo Main.Storyboard localize o View Controller de Sessão e arraste mais um Label abaixo do cronometro. Adicione constraints para manter seu centro X igual do cronometro e manter uma distância vertical de 8 pontos para ele. Modifique o título do Label para 1 de 10.

5.8. Adicione o Botão de Opções

No arquivo Main.Storyboard localize o View Controller de Sessão e arraste um Button alinhando com a parte inferior direita da view. Adicione constarias para alinha-lo a 16 pontos da borda direita e inferior.

Modifique o título do Botão para Opções.


Exercício 6: Criando Outlets para os Componentes da Tela

6.1. Abra o View Controller de Sessão com o Assistant Editor

6.2. Adicione uma seção para os Outlets

No arquivo SessionViewController.swift inclua uma sessão para os Outlets e uma separação os métodos de controle do ciclo de vida da View, conforme o código abaixo:

//
// MARK: - Outlets


//
// MARK: - View Lifecycle

6.3. Crie os Outlet dos componentes

Crie um novo Outlet para a Barra de Título com o nome titleLabel. Crie um novo Outlet para o Label de Cronometro com o nome chronometerLabel. Crie um novo Outlet para o Label de Repetições com o nome repetitionsLabel.


Exercício 7: Incluindo as funcionalidades da tela de Sessão

7.1. Inclua as propriedades necessárias na classe SessionViewController

No arquivo SessionViewController.swift incluas as propriedades necessárias conforme o código abaixo:

//
// MARK: - Properties

var sessionTrack: SessionTrack!
var activity: Activity!
var tapRecognizer: UITapGestureRecognizer!

7.2. Acrescente os métodos auxiliares

No final arquivo SessionViewController.swift incluas os métodos conforme o código abaixo:

//
// MARK: - Métodos auxiliares

func configureGestureRecognizers() {
    // Configura o gesto de Taps para receber contabilizar as repetições com os toques na tela
    self.tapRecognizer = UITapGestureRecognizer(target: self, action: "tapGestureDetected:")
    self.tapRecognizer.numberOfTapsRequired = 1
    self.view.addGestureRecognizer(self.tapRecognizer)
}

func updateUI() {
    self.repetitionsLabel.text = "\(self.sessionTrack.currentRepetitions) de \(self.activity.repetitions!)"
}

/// Esse método é chamado quando o usuário realiza o gesto de toque (tap)
func tapGestureDetected(sender: UITapGestureRecognizer) {
   sessionTrack.addRepetition()
   updateUI()
}

3. Atualize o método viewDidLoad

No arquivo SessionViewController.swift localize o método viewDidLoad e inclua o código abaixo:

// Configura os Gesture Recognizers
self.configureGestureRecognizers()

// Configura a sessão
self.sessionTrack = SessionTrack(sessionParameters: self.activity)
self.sessionTrack.updateTimerBlock = {
    if $1 != nil {
        self.chronometerLabel.text = "\($1!.getFormattedInterval(miliseconds: false))"
    } else {
        self.chronometerLabel.text = "\($0.getFormattedInterval(miliseconds: false))"
    }
}
self.sessionTrack.completionBlock = {
    // Alerta o usuário da conclusão
    let alertC = UIAlertController(title: "Traqt", message: "Sessão concluida.", preferredStyle: .Alert)
    alertC.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) { (alert: UIAlertAction!) -> Void in
        self.dismissViewControllerAnimated(true, completion: nil)
        })

    self.presentViewController(alertC, animated: true, completion: nil)
}
self.sessionTrack.startSession()

// Configura a apresentação
self.titleLabel.text = self.activity.name
self.updateUI()

Exercício 8: Mostrando as Opções

8.1. Crie uma seção de Action Methods na classe SessionViewController

No arquivo SessionViewController.swift inclua uma seção para Action Methods no final, conforme o código abaixo:

//
// MARK: - Action Methods

8.2. Crie um Action Method para o botão de opções

Crie um novo Action Method a partir do botão de opções com o nome optionsTapped. Atualize o código do método conforme abaixo:

@IBAction func optionsTapped(sender: UIButton) {
    presentActions()
}

8.3. Inclua o método presentActions

No arquivo SessionViewController.swift inclu o método presentActions na seção de métodos auxiliares conforme o código abaixo:

func presentActions() {
    // Cria um UIAlertController do tipo Commands Sheet para apresentar as opções
    let commandsSheet = UIAlertController(title: "Atividade em Andamento", message: "Comandos disponíveis para a sessão.", preferredStyle: .ActionSheet)

    // Comandos de pause/retomada
    if self.sessionTrack.sessionState == .Running {
        let actionPause = UIAlertAction(title: "Pausar", style: .Default) { [weak session = self.sessionTrack] (alert) in session!.pauseSession() }
        commandsSheet.addAction(actionPause)
    } else if self.sessionTrack.sessionState == .Paused {
        let actionResume = UIAlertAction(title: "Retomar", style: .Default) { [weak session = self.sessionTrack] (alert) in session!.resumeSession() }
        commandsSheet.addAction(actionResume)
    }

    // Comando de habilitar/desabilitar vibração
    let title = sessionTrack!.enableVibration ? "Desabilitar Vibração" : "Habilitar Vibração"
    commandsSheet.addAction(UIAlertAction(title: title, style: .Default) { (alert) in self.sessionTrack!.enableVibration = !self.sessionTrack!.enableVibration })

    // Outros comandos
    commandsSheet.addAction(UIAlertAction(title: "Parar Sessão", style: .Destructive) { (alert) in self.dismissViewControllerAnimated(true, completion: nil) })
    commandsSheet.addAction(UIAlertAction(title: "Cancelar", style: .Cancel, handler: nil))

    // Usado como workaround com um bug do iOS 8
    dispatch_async(dispatch_get_main_queue()) {
        // Apresenta o commands sheet
        self.presentViewController(commandsSheet, animated: true, completion: nil)
    }
}

Exercício 9: Passando a atividade selecionada para a tela de Sessão

9.1. Crie um Segue do tipo Present Modally entre o View Controller de Início e o de Sessão

Modifique a propriedade identifier do Segue para StartSession.

9.2. Inclua uma seção para Action Metidos na classe NewSessionViewController

No arquivo NewSessionViewController.swift inclua uma seção para Action Methods conforme o código abaixo:

//
// MARK: - Action Methods

9.3. Crie um novo Action Method para o botão Iniciar Atividade

No arquivo NewSessionViewController.swift crie um novo Action Method a partir do botão Iniciar Atividade com o código abaixo:

@IBAction func startSession(sender: UIButton) {
    if let _ = self.selectedActivity {
        self.performSegueWithIdentifier("StartSession", sender: self)
    } else {
        // 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)
    }
}

9.4. Inclua a implementação do método prepareForSegue:vender:

No arquivo NewSessionViewController.swift inclua a implementação do método conforme o código abaixo:

//
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "StartSession" {
        let destVC = segue.destinationViewController as! SessionViewController
        destVC.activity = self.selectedActivity
    }
}

Exercício 10: Alterando a cor da barra de status

10.1. Alterar a cor da barra de Status no Designer do Storyboard

10.2. Inclua o código para alterar a cor da barra de status

No arquivo SessionViewController.swift inclua o código abaixo:

override func preferredStatusBarStyle() -> UIStatusBarStyle {
    return UIStatusBarStyle.LightContent
}