2017-04-25 9 views
7

Próbuję nauczyć się używać Realm Swift i Charts, więc mogę w końcu użyć ich zarówno w aplikacji, którą buduję, i mam piekło czasu wymyślając Królestwo. W końcu planuję mieć wykresy na mojej Realm DB, a następnie wyświetlić wykresy na podstawie danych, ale zanim to zrobię, muszę sprawdzić, czy obiekt istnieje jeszcze, a jeśli nie, to stworzyć to, a użytkownik korzysta z aplikacji, dodaje do tego rekordu "zliczenia" i odpowiednio aktualizuje wykres.jak zaktualizować obiekt w świecie swift

Jak się dowiedziałem, złamałem to na kilka kroków. Ja już zorientowali się, jak sprawdzić, czy rekord istnieje i jeśli nie budować to tak:

moim królestwie Model:

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

I zostały zweryfikowane, że jego prace poprzez sferę Browser aplikacja.

Następna na mojej liście rzeczy do zrobienia jest dowiedzieć się, jak zaktualizować rekord dla "dzisiejszego rekordu daty". Aby to zrobić, stworzyłem przycisk, więc po dotknięciu spróbuje to zrobić. Szukałem google i szukałem informacji, ponieważ nie używam klucza podstawowego w moim modelu, muszę najpierw usunąć konkretny rekord, a następnie dodać go ponownie z nowymi danymi. Nie mogę na całe życie dowiedzieć się, jak to zrobić w oparciu o dokumentację Królestwa, a nawet więcej googlowania. To, co mam, ale to nie działa:

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

Kiedy dotknij przycisk btnUpdate1MW pojawia się następujący błąd w Xcode:

Zakończenie aplikację spowodowane nieprzechwyconego wyjątku „Nieprawidłowa wartość ", powód:" Oczekiwany obiekt typu data dla właściwości "data" na obiekcie typu "TreningiCount", ale otrzymał: 2017-04-24 07:00:00 +0000 '

+0

Dlaczego nie używasz klucza głównego? Jest przeznaczony do dokładnie tych scenariuszy, gdy chcesz zaktualizować istniejący obiekt. Jest łatwiejszy w użyciu niż usuwanie i odtwarzanie obiektu, a także jest bardziej optymalnym rozwiązaniem. –

+0

Ponieważ po powrocie i dodaniu klucza podstawowego zepsuł on to, co już miałem działa, błąd na linii "let realm = try! Realm()" w pierwszym zbiorze kodu powyżej i nie mogłem zrozumieć, jak to naprawić. Ponieważ zajęło mi to dzień, aby uzyskać taką pracę, czułem, że robię krok do tyłu. – jammyman34

+0

Czy dodano blok migracji do metody AppDelegate, applicationDidFinishLaunching? Jeśli nie, to był powód, dla którego dostałeś błąd i otrzymasz ten sam błąd za każdym razem, gdy zmienisz swoje modele Królestwa. –

Odpowiedz

20

Aktualizowanie obiektów jest właśnie przypisane wartość do właściwości w ramach transakcji zapisu. Zobacz naszą dokumentację.

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

Więc nie trzeba usunąć, a następnie dodać obiekt. Wystarczy przypisać nową właściwość do właściwości w transakcji zapisu, jak poniżej.

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: Proszę nie używać interpolacji napisów w zapytaniu. Zwykle konstruowanie ważnego ciągu za pomocą interpolacji ciągów znaków jest złą praktyką. Użyj składni zastępczej łańcuchów NSPredicate, takiej jak filter("date = %@", removeTodaysItem).

+0

jest sposób na ustawienie var 'treningi', więc filtruje z CONTAIN Nie mogłem znaleźć tej składni od czasu, w którym próbowałem pracować z Predicates, a dokumentacja nie jest jasna, aby pozwolić mi na sprawdź to ...i zdawałem sobie również sprawę z "nie używajcie interpolacji ciągów", ale byłem zdesperowany i to były przykłady, które znajdowałem w Internecie, ale dziękuję za wyjaśnienie :) – jammyman34

Powiązane problemy