Prática 2: Criando o Modelo

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

Exercício 1: Criando um grupo para o projeto no modelo

1.1. Criar o Grupo Model

No Project Navigator criar um grupo com o nome Model abaixo do grupo Traqt.

1.2. Configurar a pasta do Grupo Model

No File Inspector modifique o Location do grupo, criando uma subpasta chamada Model abaixo da pasta da raiz do projeto e selecionado.


Exercício 2: Criando a enumeração de estados da Sessão

2.1. Criar o arquivo SessionState.swift

Crie um novo arquivo do tipo Swift File no grupo modelo com o nome SessionState.swift.

2.2. Incluir o código do arquivo

Abra o arquivo criado no item anterior e inclua o código para declaração da enumeração.

/*
    Enumera os possíveis estados de uma sessão do Traqt
 */
enum SessionState {
    case New            // Uma sessão recém criada que ainda não foi iniciada
    case Running        // Sessão esta em andamento
    case Paused         // Sessão esta em pausa
    case Completed      // Sessão foi concluída conforme os parametros que o usuário estipulou
    case Cancelled      // O usuário cancelou a sessão antes de conclui-la conforme seus parametros
}

Exercício 3: Declarando a classe da gestão de sessão

3.1. Criar o arquivo SessionTrack.swift.

Crie um novo arquivo do tipo Swift File no grupo modelo com o nome SessionTrack.swift.

3.2. Inclua o código para declaração da classe SessionTrack

Abra o arquivo criado no item anterior e inclua o código para declaração da classe e os stubs de seus principais métodos:

/**
    Uma classe para gerenciar a sessão de uma atividade.
 */
class SessionTrack {

    //
    // MARK: - Public methods

    /**
        Inicia a sessão.
     */
    func startSession() {

    }

    /**
        Pausa a sessão caso ela esteja em andamento
     */
    func pauseSession() {

    }

    /**
        Resume a sessão caso ela esteja pausada.
     */
    func resumeSession() {

    }

    /**
        Cancela a sessão caso ela esteja em andamento.
     */
    func cancelSession() {

    }

    /**
        Adiciona uma repetição a sessão.
     */
    func addRepetition() {

    }

}

3.3. Criar o arquivo SessionParameters.swift

Crie um novo arquivo do tipo Swift File no grupo modelo com o nome SessionParameters.swift.

3.4. Inclua o código do protocolo SessionParameters

Abra o arquivo criado no item anterior e inclua o código para declaração do protocolo:

/**
    Um protocolo declarando os parâmetros usados por uma sessão
 */
protocol SessionParameters {

    /// Quantidade de repetições máximas dessa sessão
    var maxRepetitions: Int { get }

    /// Tempo limite dessa sessão
    var duration: NSTimeInterval { get }

    /// Habilitar vibrações quando uma repetição é adicionada?
    var vibrate: Bool { get }

}

3.5. Inclua uma propriedade para os parâmetros da Sessão

Abra o arquivo SessionTrack.swift e crie uma sessão de propriedades na classe SessionTrack declarando uma propriedade para os parâmetros da Sessão:

//
// MARK: - Properties

var sessionParameters: SessionParameters

3.6. O erro "Class 'SessionTrack' has no initializers' será corrigido nos próximos exercícios


Exercício 4: Adicionando o Componente de Cronometro

4.1. Integrar o componente ChronometerKit

Baixe o componente ChronometerKit a partir deste link.

4.2. Criar um Group para as bibliotecas

No Project Navigator crie um novo grupo na raiz chamado Libs. Configure a pasta do grupo.

4.3. Adicionar o componente ao projeto

Descompacte o arquivo baixado e arraste-o para dentro do projeto, seguindo as opções:

  • Destination: Copy Items if needed - deixar marcado
  • Added folders - selecionar a opção Create Groups
  • Add to Targets - Selecionar o target Traqt

Exercício 5: Implementando a Classe

5.1. Incluir propriedades na classe SessionTrack

Abra o arquivo SessionTrack.swift e inclua as seguintes propriedades:

var enableVibration: Bool
private(set) var sessionState: SessionState = .New
private(set) var currentRepetitions: Int = 0
private(set)var startTime: NSDate?
private var chronometer = Chronometer()

5.2. Inclua os métodos de apoio na classe SessionTrack

Ainda com o arquivo SessionTrack.swift aberto incluas os seguintes métodos de apoio no final da classe:

//
// MARK: - Private Methods

/**
    Esse método avalia os critérios da atividade selecionada com o estado atual da sessão para determinar se a sessão foi concluída.
 */
private func checkCompletion() {
    // Verifica se esta medindo as repetições e se o limite foi atingido
    if self.sessionParameters.maxRepetitions > 0 {
        if self.currentRepetitions >= self.sessionParameters.maxRepetitions {
            self.completeSession()      // Se a sessão foi concluída chamamos o método de apoio para encerra-la
            return
        }
    }
}

/**
    Esse método é usado para marcar uma sessão como concluída.
    :param: isCancelled Um flag indicando se a sessão foi concluída naturalmente ou se foi cancelada.
 */
private func completeSession(isCancelled: Bool = false) {
    // Verifica se o estado da sessão não é cancelado ou completo
    if sessionState != .Cancelled && sessionState != .Completed {
        self.chronometer.stop()
        self.sessionState = isCancelled ? .Cancelled : .Completed
    }
}

5.3. Inclua o inicializador da classe

No arquivo SessionTrack.swift inclua o código do inicializador abaixo da declaração das propriedades:

//
// MARK: - Initializers

/**
    Cria uma instância dessa classe de acordo com as configurações dos parâmetros.

    :param: sessionParameters Um objeto que obedeça ao protocolo "SessionParameter", estipulando os parâmetros que o usuário deseja para a sessão.
 */
init(sessionParameters: SessionParameters) {
    // Configura as propriedades dessa instância de acordo com os parâmetros recebidos
    self.sessionParameters = sessionParameters
    self.enableVibration = sessionParameters.vibrate

    // Configura o cronometro caso um tempo limite seja estipulado
    if self.sessionParameters.duration > 0 {
        self.chronometer.setLimit(self.sessionParameters.duration) {
            self.completeSession()
        }
    }
}

Exercício 6: Implementando os Métodos Públicos

6.1. Inclua o código dos métodos startSession e cancelSession

No arquivo SessionTrack.swift incluir a implementação dos métodos conforme o código abaixo:

func startSession() {
    // Só deve fazer alguma coisa se a sessão for nova
    if sessionState == .New {
        self.startTime = NSDate()       // Marca o horário de início
        self.chronometer.start()
        self.sessionState = .Running
    }
}

func cancelSession() {
    self.completeSession(true)
}

6.2. Inclua o código dos métodos pauseSession e resumeSession

No arquivo SessionTrack.swift incluir a implementação dos métodos conforme o código abaixo:

func pauseSession() {
    if sessionState == .Running {
        self.chronometer.stop()
        self.sessionState = .Paused
    }
}

func resumeSession() {
    if sessionState == .Paused {
        self.chronometer.start()
        self.sessionState = .Running
    }
}

6.3. Importar a biblioteca AudioToolbox

No arquivo SessionTrack.swift Importar a biblioteca AudtioToolBox necessária para a inclusão da função de vibração usando o código abaixo:

import AudioToolbox

6.4. Inclua o código do método addRepetition

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

func addRepetition() {
    if sessionState == .Running {
        // Vibra o dispositivo
        if self.enableVibration {
            AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
        }

        self.currentRepetitions++
        self.checkCompletion()
    }
}

Exercício 7: Comunicando-se com o usuário do objeto

7.1. Incluir as propriedades para a comunicação de eventos

No arquivo SessionTrack.swift incluir as propriedades conforme o código abaixo:

var updateTimerBlock: ChronometerUpdateBlock {
    willSet {
        self.chronometer.updateBlock = newValue
    }
}
var completionBlock: (() -> ())?

7.2. Inclua a chamada para o evento de Sessão completa

No arquivo SessionTrack.swift atualize a implementação do método completeSession conforme o código abaixo:

private func completeSession(isCancelled: Bool = false) {
    // Verifica se o estado da sessão não é cancelado ou completo
    if sessionState != .Cancelled && sessionState != .Completed {
        self.chronometer.stop()
        self.sessionState = isCancelled ? .Cancelled : .Completed
        self.completionBlock?()     // Informa o usuário dessa instância qua a sessão foi concluída
    }
}