Prática 2: Integrando o Core Data

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

Exercício 1: Apresentando a Lista de Atividades

1.1. Remover as propriedades dos Text Fields

No arquivo ViewController.swift remover as propriedades repetitionsLimitTextField e timeLimitTextField.

1.2. Remover o código de inicialização do Text Fields

No arquivo ViewController.swift no método viewDidLoad localizar e remover os trechos de código abaixo:


// Cria o botão de reinicio da sessão
let resetButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
resetButton.setTitle("Reiniciar", forState: UIControlState.Normal)
resetButton.sizeToFit()
resetButton.frame = CGRect(x: (self.view.frame.size.width / 2 - resetButton.frame.size.width / 2),
   y: 28,
   width: resetButton.frame.size.width,
   height: resetButton.frame.size.height)
resetButton.addTarget(self, action: "handleResetButton:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(resetButton)

// Cria o UITextField para configurar o limite de repetições
self.view.addSubview(self.repetitionsLimitTextField)
self.view.addSubview(self.timeLimitTextField)

1.3. Atualizar o código das propriedades maxRepetitions e duration

No arquivo ViewController.swift atualize as propriedades de acordo com o código abaixo:

var maxRepetitions: Int {

    if let r = self.repetitionsLimitTextField.text.toInt() {
        return r
    }

    return 0
}
var duration: NSTimeInterval {

    if let tl = self.timeLimitTextField.text.toInt() {
        return NSTimeInterval(tl)
    }

    return NSTimeInterval(0)
}

1.4. Incluir as propriedades do Data Context

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

lazy var activities: [Activity] = {
    let acts = TraqtDataContext.sharedInstance.activities.getAll()
    return acts
    }()
var currentActivity: Activity!  {
    didSet {
        self.configSession()
    }
}

1.5. Incluir o UIPickverView de seleção de atividades

No arquivo ViewController.swift incluir o código para declaração do UIPickverView no método viewDidLoad:

// Cria o picker view de listagem e seleção de atividades
let pickerFrame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 100)
let activityPicker = UIPickerView(frame: pickerFrame)
activityPicker.delegate = self
activityPicker.dataSource = self
activityPicker.showsSelectionIndicator = true
self.view.addSubview(activityPicker)

1.6. Declarar a classe ViewController como aderente aos protocolos do UIPickerView

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

class ViewController: UIViewController, SessionParameters<b>, UIPickerViewDelegate, UIPickerViewDataSource</b> {

1.7. Inserir o código dos métodos necessários dos protocolos

No arquivo ViewContoller.swift incluir os métodos dos protocolos conforme 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) {
    // Alterna a seleção da atividade atual e reinicia a sessão
    self.sessionTrack.cancelSession()
    self.currentActivity = self.activities[row]
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return self.activities[row].name
}

1.8. Executar o App e verificar a carga do Picker View

1.9. Adicionar uma Extension para tornar a classe Acitvity aderente ao protocolo SessionParameters

No grupo Model crie um novo arquivo do tipo Swift File com o nome Activity+SessionParameters.swift e adicione o seguinte código:

extension Activity : SessionParameters {

    /// Quantidade de repetições máximas dessa sessão
    var maxRepetitions: Int {
        return repetitions!.integerValue
    }

    /// Duração da sessão
    var duration: NSTimeInterval {
        return NSTimeInterval(timeLimit?.floatValue ?? 0)
    }

    /// Habilitar vibrações quando uma repetição é adicionada?
    var vibrate: Bool {
        return enableVibration?.boolValue ?? false
    }

}

1.10. Remova a implementação do protocolo SesionParameters da classe ViewController

No arquivo ViewController.swift localize e remova todas as referencias ao protocolo SessionParameters:

  • Exclua as propriedades maxRepetitions, duration e vibrate
  • Exclua a declaração de aderência ao protocolo na declaração da classe, conforme o código abaixo:
class ViewController: UIViewController,  SessionParameters, UIPickerViewDelegate, UIPickerViewDataSource {

1.11. Atualize o método handleVibrationsButton:sender:

No arquivo ViewController.swift localize e atualize o método conforme o código abaixo:

func handleVibrationsButton(sender: UIButton) {
    self.sessionTrack.enableVibration = !self.sessionTrack.enableVibration

    let title = self.sessionTrack.enableVibration ? "Desabilitar Vibração" : "Habilitar Vibração"
    sender.setTitle(title, forState: UIControlState.Normal)
}

1.12. Atualize a implementação do método configSession

No arquivo ViewControlle.swift localize e atualize o método conforme o código abaixo:

func configSession() {
    self.sessionTrack = SessionTrack(sessionParameters: self)
    self.sessionTrack = SessionTrack(sessionParameters: self.currentActivity)

    // Restante do código
    // ...
}

1.13. Inclua a inicialização da propriedade currentActivity

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

// Configura a sessão
self.currentActivity = self.activities[0]
self.configSession()

1.14. Inclua as propriedades para os Labels de exibição das configurações da atividade selecionada

No arquivo ViewController.swift inclua as propriedades conforme o código abaixo:

lazy var maxRepetitionsLabel: UILabel = {
    let label = UILabel(frame: CGRect(x: 20, y: 180, width: 100, height: 100))
    label.text = "Repetições max.: 0"
    label.sizeToFit()
    return label
}()
lazy var durationLabel: UILabel = {
    let label = UILabel(frame: CGRect(x: 20, y: 200, width: 100, height: 100))
    label.text = "Tempo limite: 0"
    label.sizeToFit()
    return label
}()

1.15. Inclua os Labels na View Principal

No arquivo ViewController.swift inclua os labels criados no item anterior, no método viewDidLoad conforme o código abaixo:

// Adiciona os outros componentes
self.view.addSubview(self.maxRepetitionsLabel)
self.view.addSubview(self.durationLabel)

1.16. Atualize a propriedade currentActivity

No arquivo ViewController.swift atualize a propriedade conforme o código abaixo:

var currentActivity: Activity! {
    didSet {
        self.configSession()

        // Atualiza os dados da atividade
        self.maxRepetitionsLabel.text = "Repetições max.: \(self.currentActivity?.repetitions ?? 0)"
        self.maxRepetitionsLabel.sizeToFit()
        self.durationLabel.text = "Tempo limite: \(self.currentActivity.duration.getFormattedInterval(miliseconds: false))"
        self.durationLabel.sizeToFit()
    }
}

Exercício 2: Salvando e Apresentando Sessões

2.1. Criar um arquivo para a enumeração SessionOutcome

No grupo Model inserir um novo arquivo do tipo Swift File com o nome SessionOutcome.swift e incluir o código abaixo:

/// Enumera os status com o qual uma sessão pode ser concluída
enum SessionOutcome : Int {

    /// A sessão foi concluída normalmente
    case Completed

    /// A sessão foi cancelada
    case Cancelled

}

2.2. Atualize o protocolo SessionParameters

Abra o arquivo SessionParameters.swift e atualize o protocolo inserindo o método conforme o código abaixo:

/// Salva uma sessão
func saveSession(outcome: SessionOutcome, startTime: NSDate, endTime: NSDate, elapsedTime: NSTimeInterval, totalRepetitions: Int)

2.3. Inclua a implementação do método na classe Activity

Abra o arquivo Activity+SessionParameters.swift e acrescente o código do novo método do protocolo conforme o código abaixo:

/**
    Salva uma sessão na entidade de Sessões, associada a esta atividade.

    - Parameters:
        - outcome: Status com o qual a sessão foi concluída.
        - startTime: Data/horário de início da sessão.
        - endTime: Data/horário de conclusão da sessão.
        - elapsedTime: Tempo transcorrido.
        - totalRepetitions: Quantidade total de repetições.
 */
func saveSession(outcome: SessionOutcome, startTime: NSDate, endTime: NSDate, elapsedTime: NSTimeInterval, totalRepetitions: Int) {
    TraqtDataContext.sharedInstance.sessions.add() {
        $0.activitiy = self
        $0.sessionOutcome = outcome.rawValue
        $0.startTime = startTime
        $0.endTime = endTime
        $0.elapsedTime = elapsedTime
        $0.totalRepetitions = totalRepetitions
    }
}

2.4. Atualize o método completeSession

Abra o arquivo SessionTrack.swift e atualize o método 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 == .Running || sessionState == .Paused {
       self.chronometer.stop()
       self.sessionState = isCancelled ? .Cancelled : .Completed

       // Salva a sessão
       let outcome = isCancelled ? SessionOutcome.Cancelled : SessionOutcome.Completed
       self.sessionParameters.saveSession(outcome, startTime: self.startTime ?? NSDate(), endTime: NSDate(), elapsedTime: self.chronometer.elapsedTime, totalRepetitions: self.currentRepetitions)

       // Informa o usuário dessa instância qua a sessão foi concluída
       self.completionBlock?()
   }
}

2.5. Adicione um TextView para histórico na view principal

No arquivo ViewController.swift adicione a propriedade conforme o código abaixo:

lazy var sessionsTextView: UITextView = {
    let textView = UITextView(frame: CGRect(x: 0, y: self.view.center.y + 60, width: self.view.frame.width, height: 100))
    return textView
}()

E adicione o componente a view principal no método viewDidLoad conforme o código abaixo:

self.view.addSubview(self.sessionsTextView)

2.6. Atualize a propriedade currentActivity

No arquivo ViewController.swift atualize a propriedade conforme o código abaixo:

var currentActivity: Activity! {
    didSet {
        self.configSession()

        // Atualiza os dados da atividade
        self.maxRepetitionsLabel.text = "Repetições max.: \(self.currentActivity.repetitions)"
        self.maxRepetitionsLabel.sizeToFit()
        self.durationLabel.text = "Tempo limite: \(self.currentActivity.duration.getFormattedInterval(miliseconds: false))"
        self.durationLabel.sizeToFit()

        // Mostra as sessões realizadas no TextView
        if let sessions = self.currentActivity.sessions where sessions.count > 0 {
            let dateFormatter = NSDateFormatter()
            dateFormatter.dateStyle = .ShortStyle
            dateFormatter.timeStyle = .ShortStyle

            var sessionHistory = "Sessões desta atividade:"
            for session in sessions {
                let s = session as! Session
                sessionHistory += "\n- Sessão em \(dateFormatter.stringFromDate(s.startTime!)), repetições: \(s.totalRepetitions ?? 0), tempo: \(NSTimeInterval(s.elapsedTime ?? 0).getFormattedInterval(miliseconds: false))"
            }
            self.sessionsTextView.text = sessionHistory
        } else {
            self.sessionsTextView.text = "Não há sessões registradas para essa atividade."
        }
    }
}