
Dans ce chapitre, nous allons utiliser notre entité Spending pour sauvegarder les dépenses.
Jusqu'à présent, le mécanisme qu'on utilisait pour sauvegarder les dépenses, c'était SpendingRepository. Cette classe utilisait le Singleton Pattern pour stocker les données dans un tableau spendings.
Bien sûr, maintenant on va utiliser Core Data, donc je vous invite à aller dans le fichier SpendingRepository...
Les dépenses sont ajoutées dans l'interface AddSpendingViewController lors de l'appui sur le bouton Save. Côté code, cela a lieu dans la méthode save que voici :
@IBAction private func save() {
guard
let content = contentTextField.text,
let amountText = amountTextField.text,
let amount = Double(amountText)
else { return }
let spending = Spending(content: content, amount: amount)
spendingRepository.add(spending: spending)
navigationController?.popViewController(animated: true)
}Cette méthode fait trois choses :
Elle récupère les informations du formulaire.
Elle crée et sauvegarde un objet Spending avec SpendingRepository.
Elle renvoie l'utilisateur vers la liste des dépenses.
Bien sûr, nous allons modifier la deuxième étape. Comme dans notre PeopleRepository, nous allons utiliser notre singleton du CoreDataStack pour traiter les sauvegardes dans CoreData.
import Foundation
final class SpendingRepository {
// MARK: - Properties
private let coreDataStack: CoreDataStack
// MARK: - Init
init(coreDataStack: CoreDataStack = CoreDataStack.sharedInstance) {
self.coreDataStack = coreDataStack
}
// MARK: - Repository
func addSpending(with amount: Double, content: String, completion: () -> Void) {
let spending = Spending(context: coreDataStack.viewContext)
spending.amount = amount
spending.content = content
do {
try coreDataStack.viewContext.save()
completion()
} catch {
print("We were unable to save \(spending)")
}
}
}À présent, nous avons encore une closure d'exécution disponible, que nous allons utiliser côté contrôleur :
// MARK: - Actions
@IBAction private func save() {
guard
let content = contentTextField.text,
let amountText = amountTextField.text,
let amount = Double(amountText)
else { return }
spendingRepository.addSpending(
with: amount,
content: content,
completion: { [weak self] in
self?.navigationController?.popViewController(animated: true)
})
}On voit ici que la méthode popViewController est à présent appelée au moment de l'exécution de la closure. C'est-à-dire qu’elle est appelée lorsque notre repository appelle la méthode completion() dans le bloc do-catch après avoir réussi à sauvegarder notre objet Spending.
Notre objet Spending a une troisième propriété : person. Cette propriété fait le lien avec notre autre entité Person. Pour créer la relation, il nous suffit de donner à la propriété la personne choisie par l'utilisateur dans le Picker View.
On commence par mettre à jour notre méthode addSpending dans notre SpendingsRepository :
func addSpending(with amount: Double, content: String, for person: Person, completion: () -> Void) {
let spending = Spending(context: coreDataStack.viewContext)
spending.amount = amount
spending.content = content
spending.person = person
do {
try coreDataStack.viewContext.save()
completion()
} catch {
print("We were unable to save \(spending)")
}
}Puis, on va récupérer cette personne dans une méthode privée à part de notre AddSpendingViewController :
private func getSelectedPerson() -> Person? {
if !people.isEmpty {
let index = personPickerView.selectedRow(inComponent: 0)
return people[index]
}
return nil
}On la récupère dans notre tableau people en utilisant l'index de la ligne sélectionnée par l'utilisateur dans le Picker View.
Ensuite, on va l'utiliser au moment de l’appel à notre repository pour la création de la dépense, et le code complet donne :
@IBAction private func save() {
guard
let content = contentTextField.text,
let amountText = amountTextField.text,
let amount = Double(amountText),
let person = getSelectedPerson()
else { return }
spendingRepository.addSpending(
with: amount,
content: content,
for: person,
completion: { [weak self] in
self?.navigationController?.popViewController(animated: true)
})
}
private func getSelectedPerson() -> Person? {
if !people.isEmpty {
let index = personPickerView.selectedRow(inComponent: 0)
return people[index]
}
return nil
}On utilise tout simplement la propriété person. On fait toujours de l'orienté objet classique !
Et voilà, notre dépense est sauvegardée dans Core Data ! Dans le prochain chapitre, nous allons récupérer nos données pour les afficher dans notre liste de dépenses.