web-dev-qa-db-fra.com

comment mettre à jour un objet dans le royaume swift

J'essaie d'apprendre comment utiliser Realm Swift et les graphiques afin de pouvoir les utiliser tous les deux dans une application que je suis en train de construire et où j'ai énormément de mal à découvrir Realm. En fin de compte, j’ai l’intention de demander à Charts de consulter ma base de données de domaines, puis d’afficher les graphiques en fonction des données, mais avant cela, j’ai besoin de vérifier si un objet de domaine existe déjà, si ce n’est pas le cas, pour le créer. puis, à mesure que l'utilisateur utilise l'application, ajoutez des "comptes" à cet enregistrement et mettez le graphique à jour en conséquence.

Comme je suis en train d'apprendre, j'ai divisé cela en étapes. J'ai déjà compris comment vérifier si un enregistrement existe et sinon le construire comme ceci:

Mon modèle de royaume:

class WorkoutsCount: Object{    
    dynamic var date: Date = Date()
    dynamic var count: Int = Int(0)
}

// function to check if this weeks days have been created in Realm DB yet and creates them if not
    let realm = try! Realm()
    lazy var workouts: Results<WorkoutsCount> = { self.realm.objects(WorkoutsCount.self)}()
    let startOfWeekDate = Date().startOfWeek(weekday: 1)
    let nextDay = 24 * 60 * 60

    // checks the DB to see if it contains the start of this week
    func searchForDB(findDate: Date) -> WorkoutsCount?{
        let predicate = NSPredicate(format: "date = %@", findDate as CVarArg)
        let dateObject = self.realm.objects(WorkoutsCount.self).filter(predicate).first

        if dateObject?.date == findDate{
            return dateObject
        }
        return nil
    }

    func setThisWeeksDays(){
        //if the beginning of this week doesn't exist in the DB then create each day with 0's as the count data
        if searchForDB(findDate: startOfWeekDate) == nil{
            try! realm.write() {

                let defaultWorkoutDates = [startOfWeekDate, startOfWeekDate + TimeInterval(nextDay), startOfWeekDate + TimeInterval(nextDay*2), startOfWeekDate + TimeInterval(nextDay*3), startOfWeekDate + TimeInterval(nextDay*4), startOfWeekDate + TimeInterval(nextDay*5), startOfWeekDate + TimeInterval(nextDay*6)]

                for workouts in defaultWorkoutDates {
                    let newWorkoutDate = WorkoutsCount()
                    newWorkoutDate.date = workouts
                    self.realm.add(newWorkoutDate)
                }
            }            
            workouts = realm.objects(WorkoutsCount.self)
        }
    }

J'ai vérifié que ses œuvres via l'application Realm Browser.

La prochaine étape de ma liste de tâches consiste à déterminer comment mettre à jour un enregistrement pour "enregistrement de la date du jour". Pour ce faire, j'ai créé un bouton afin que, lorsqu'il est tapé, il tente de le faire. Je suis en train de googler et de googler, et depuis que je n'utilise pas de clé primaire dans mon modèle, je dois d'abord supprimer l'enregistrement spécifique en question, puis l'ajouter à nouveau avec les nouvelles données. Je ne peux pas pendant toute ma vie comprendre comment faire cela en se basant sur la documentation de Realm et sur encore plus de recherches sur Google. C'est ce que j'ai, bien que cela ne fonctionne pas:

@IBAction func btnUpdate1MW(_ sender: Any) {
        if searchForDB(findDate: today) != nil{
            if plusOne <= 7{
                plusOne += 1
                CounterImage1MW.image = UIImage(named:  "1MWs-done-\(plusOne)")

                let realm:Realm = try! Realm()

                // deletes the original item prior to being updated and added back below
                let removeTodaysItem = today
                let workout = realm.objects(WorkoutsCount.self).filter("date = '\(removeTodaysItem)'")
                if workout.count > 0{
                    for date in workout{
                        try! realm.write {
                            realm.delete(date)
                        }
                    }
                }
                // adds back the item with an updated count
                do {
                    let realm = try Realm()
                    try realm.write {
                        realm.create(WorkoutsCount.self, value: ["date": today, "count": plusOne], update: false)
                    }
                } catch let error as NSError {
                    fatalError(error.localizedDescription)
                }
            }

            print("add to 1MW + 1")
        }
    }

Lorsque j'appuie sur le bouton btnUpdate1MW, l'erreur suivante apparaît dans Xcode:

Arrêt de l'application en raison d'une exception non interceptée 'Valeur non valide', motif: 'Objet attendu du type date pour la propriété' date 'sur l'objet de type' WorkoutsCount ', mais reçu: 2017-04-24 07:00:00 +0000'

18
jammyman34

La mise à jour des objets consiste simplement à attribuer une valeur à une propriété dans une transaction d'écriture. Voir notre documentation.

https://realm.io/docs/Swift/latest/#updating-objects

Donc, vous n'avez pas besoin de supprimer puis d'ajouter un objet. Attribuez simplement une nouvelle valeur à la propriété dans une transaction d'écriture comme suit.

let workouts = realm.objects(WorkoutsCount.self).filter("date = %@", removeTodaysItem)

let realm = try! Realm()
if let workout = workouts.first {
    try! realm.write {
        workout.date = today
        workout.count = plusOne
    }
}

FYI: S'il vous plaît, n'utilisez pas l'interpolation de chaîne dans une requête. Généralement, construire une chaîne importante par interpolation de chaîne est une mauvaise pratique. Utilisez la syntaxe de substitution de chaîne de NSPredicate telle que filter("date = %@", removeTodaysItem).

48
kishikawa katsumi