I have a strange thing happening to my objects in an array. Every time I save the parent object, this array doubles the objects in the array. To add to the confusion, it’s not the first array (relation) that doubles, it’s further down the line.
Object:
Week -> Day -> Meal -> Portion
There are 7 days in the week, as an array
There are 4 Meals in the day, as an array
The last array, Portion, get added by appending to the portions array on the Meal object.
However every time I save the Week object, the portions double. eg. they get added to the table.
None of the other arrays do this. e.g. the days stay as 7 and the meals are 7*4=28.
Any help would be gratefully aprecaited.
class FDWeek: BackendlessEntity {
var user = Backendless.sharedInstance().userService.currentUser
var startDate: NSDate = NSDate()
var weight: Double = 0.0
var suppPlan: String = ""
var days: [FDDay] = []
class FDDay : NSObject {
var diaryDate: NSDate = NSDate()
var water: Double = 0.0
var alcohol: Double = 0.0
var bm: Int = 0
var supps: Bool = false
var training: Bool = false
var targetP: Double = 0.0
var targetF: Double = 0.0
var targetC: Double = 0.0
var targetV: Double = 0.0
var bedTime: NSDate = NSDate()
var wakeUpTime: NSDate = NSDate()
var sleepQuaity: Int = 0
var energyLevel: Int = 0
var meals: [FDMeal] = []
class FDMeal: NSObject {
var time: NSDate
var planned: Bool
var achieved: Bool
var targetProtein: Double
var targetCarb: Double
var targetFat: Double
var targetVeg: Double
var note: String
var photoPath: String
var portions: [FDPortion] = []
class FDPortion: NSObject {
var portion: String
var portionSize: Double
var portionType: String // F,P,C,V
let portion = FDPortion()
portion.portionType = typeTF.text!
portion.portion = nameTF.text!
portion.portionSize = (sizeTF.text! as NSString).doubleValue
currentMeal.portions.append(portion)
func saveToServer() {
MMProgressHUD.showWithStatus("Saving")
let dataStore = Backendless.sharedInstance().data.of(FDWeek.ofClass())
dataStore.save(
self,
response: { (result: AnyObject!) -> Void in
let obj = result as! FDWeek
debugPrint("Food Diary Week has been saved: \(obj.objectId)")
MMProgressHUD.dismissAfterDelay(0.5)
NSNotificationCenter.defaultCenter().postNotificationName("dataSaved", object: nil)
},
error: { (fault: Fault!) -> Void in
debugPrint("Server reported an error: \(fault)")
MMProgressHUD.dismissWithError("Please try later", title: "Server Error!", afterDelay: 4)
})
}
Further investigation shows the following;
A. If I start out with 3 portions from the server and tap save. There are no changes.
B. If I add one portion to the 3 that is already there and save, I get 4 portions on the server.
C. If I save again I get the last portion added again, and again…
Is there a “dirty data” flag somewhere that can be accessed?
Hi Jorgen,
Backendless use objectId field to determine previously saved objects. As Portion class does not contains objectId Backendless considers it as new object each time you save parent object. Please, add property objectId to required class and try current case. This page can be useful.
Regards,
Denys
Thank for your help.
I added objectId to FDPortion, as suggested, but I am now getting an error when saving;
"Server reported an error: FAULT = ‘1000’ [Entity with the specified ID cannot be found: Id - ] <Entity with the specified ID cannot be found: Id - > "
Code for class;
class FDPortion: NSObject {
var portion: String
var portionSize: Double
var portionType: String // F,P,C,V
var objectId: String
override init() {
portion = ""
portionSize = 0.0
portionType = ""
objectId = ""
}
}
Hi Jorgen,
ObjectId should not be empty string. It should be null for new entity.
Regards,
Denys
I can’t assign NSNULL to a String.
I think objectId should be declared as
var objectId: String?
This page can also be useful https://backendless.com/documentation/data/ios/data_relations_save_update.htm.
I’ve been following that one.
I still have the problem that when I have saved the week after adding a portion, if I save the week again directly I get another portion added. Would I need to reload the week to stop this happening? If I navigate out to the list of weeks and pick up the same week again and go to the same day. If I now save the week there is no added portion.
Still no joy.
Here is my saving function in FDWeek;
func updateOnServer() -> FDWeek? {
MMProgressHUD.showWithStatus("Saving")
let backendless = Backendless.sharedInstance()
var error: Fault?
let result = backendless.data.save(self, error: &error) as? FDWeek
if error == nil {
debugPrint("Week is updated: \(result?.objectId)")
MMProgressHUD.dismissAfterDelay(0.5)
return result!
} else {
debugPrint("Server reported an error: \(error)")
MMProgressHUD.dismissWithError("\(error!.message)", title: "Server Error!", afterDelay: 4)
return nil
}
}
// called like this in the DayVC
self.currentWeek = self.currentWeek.updateOnServer()!
Hi Jorgen,
Please, try add objectId property to each class or just extend them from BackendlessEntity.
The thing is it is necessery to load related entities with either relation depth or autoload before updating deepest related entity.
You can retrieve FDWeek with relation depth 4, add new Portion and save the whole hierarchy again.
Regards,
Denys
I did add objectId to each class with no joy. I’ll see if it makes any difference if I extend them from the BackendlessEntity instead.
Still having problems.
I changed all object so they are extend from BackendlessEntity.
If I save the FDMeal on the meal screen, the portions get saved properly, and I can add another portion and save the meal again.
However, if I got back to the day screen and save there, which saves the FDWeek), the portion array doubles.
That means related entities are not properly loaded before updates. It could be fixed if set autoload on all columns with relations
They are set;
Week is autoloading Days, which is autoloading Meals, which is autoloading Portions
Should I load the Week after saving to server? Would that not double up the API calls?
I you save object to Backendless it will be returned with objectId field and you can update it without reloading
I’ll try that idea.
BTW, did you ever get a way of synchronise Core Data from iOS? It might be an easier way of doing what I’m trying to do. That way the Core Data would be the local store and only update Backendless when needed.
Such feature are in our todo-list but it is hard to predict when it would be implemented and released