web-dev-qa-db-ja.com

レルム内のオブジェクトを更新する方法swift

Realm SwiftとChartsを使用する方法を学ぼうとしているので、最終的には作成中のアプリとRealmを理解するのに苦労しています。最終的には、チャートでRealm DBを調べ、データに基づいてチャートを表示することを計画していますが、その前に、作成するために、レルムオブジェクトがまだ存在するかどうかを確認する必要がありますその後、ユーザーがアプリを使用するときに、そのレコードに「カウント」を追加し、それに応じてグラフを更新します。

私が学んでいる間、私はこれをステップに分解しました。レコードが存在するかどうかを確認し、そうでない場合は次のように作成する方法を既に考えました。

私のレルムモデル:

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)
        }
    }

Realm Browserアプリを介して彼の作品を検証しました。

次に行うことは、「今日の日付のレコード」のレコードを更新する方法を見つけることです。これを行うには、ボタンを作成し、タップするとこれを実行しようとします。私はグーグルとグーグルをしていて、モデルで主キーを使用しないので、最初に問題の特定のレコードを削除してから、新しいデータで再度追加する必要があると考えてきました。 Realmのドキュメントやさらにグーグルに基づいてこれを行う方法を理解することはできません。これは私が持っているものですが、動作しません:

@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")
        }
    }

BtnUpdate1MWボタンをタップすると、Xcodeで次のエラーが表示されます。

キャッチされていない例外 'Invalid value'によるアプリの終了、理由: 'タイプ' WorkoutsCount 'のオブジェクトのプロパティ' date 'のタイプdateのオブジェクトが必要ですが、受信:2017-04-24 07:00:00 +0000'

18
jammyman34

オブジェクトの更新は、書き込みトランザクション内のプロパティに値を割り当てるだけです。ドキュメントをご覧ください。

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

そのため、オブジェクトを削除してから追加する必要はありません。次のように、書き込みトランザクションでプロパティに新しい値を割り当てるだけです。

_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
    }
}
_

参考までに、クエリでは文字列補間を使用しないでください。一般に、文字列補間によって重要な文字列を作成するのは悪い習慣です。 filter("date = %@", removeTodaysItem)のようなNSPredicateの文字列置換構文を使用します。

48