I think I'm getting somewhere now but I'm getting a [NSNull managedObjectContext]: . I'm not saving anything null/nil in either entities... Does anyone have any ideas why it's giving me this error?
Since I cannot delete the original post, I'll just add the update here. How do you save a new parent and child entity at the same time? The reason why it's giving me NSNull error is because it does not save the reference to person in the Note collection when person and note are being saved for the first time. BUT when the person is already saved and I add a note, then it saves correctly and doesn't give me a NSNull error. I now have a work around but I was wondering if there is a way to save both new entities at the same time.
Thanks guys!
I'm working with Persisting Core Data Objects to Kinvey but when I try to query/load from the KCSLinkedAppdataStore, I get "CoreData: error: Failed to call designated initializer on NSManagedObject class 'WHATEVER THE CLASS NAME IS'". Any help with this?
This should be the last thing before I get the app fully working with Kinvey.
I'm working with Persisting Core Data Objects to Kinvey but when I try to query/load from the KCSLinkedAppdataStore, I get "CoreData: error: Failed to call designated initializer on NSManagedObject class 'WHATEVER THE CLASS NAME IS'". Any help with this?
This should be the last thing before I get the app fully working with Kinvey.
Hello Brian,
One of our technical support engineers has been assigned to this problem. He will be asking you additional questions and providing feedback shortly. In the meantime, can you answer the following questions for us?
What platform are you using to develop your app?
What Kinvey SDK and version are you using to build your app?
Are you porting your app from another platform or are you building it from scratch using Kinvey?
Regards,
Billy Gee
Update: Loading and querying using KCSLinkedAppdataStore gives me this error, CoreData: error: Failed to call designated initializer on NSManagedObject class. It will also call
+ (id)kinveyDesignatedInitializer:(NSDictionary *)jsonDocument
in Person.m and give me error, Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MONotes 0x15d7f3260> setValue:forUndefinedKey:]: the entity (null) is not key value coding-compliant for the key "dateAdded".'
This only happens when the there are relational data (Notes add to Person). Would I have to use a pre/post hook on the Person Collection so that it doesn't return Notes and then load/query Notes Collection?
Answers to your questions Billy Gee:
1) Platform = Xcode/iOS
2) Kinvey SDK/Version = 1.40.7
3) Built it from scratch and trying to add Kinvey
Thanks,
Pranav
Kinvey Support
For http://devcenter.kinvey.com/ios/guides/troubleshooting#KeyValueCodingCompliantcrashes, if I unmap Notes from Person in hostToKinveyPropertyMapping, wouldn't that mess up the saving part of it?
For http://www.kinvey.com/how-to-model-data-relationships-in-your-kinvey-backend/, it doesn't show me the code snippet and it gives me {gist:1929275.js?file=DeweyREST.txt}.
Saving
KCSLinkedAppdataStore* store = [KCSLinkedAppdataStore storeWithCollection:[KCSCollection collectionFromString:@"Person" ofClass:[MOPerson class]] options:nil]; if (!person.thumbnailId) { NSData* data = person.thumbnail; [KCSFileStore uploadData:data options:nil completionBlock:^(KCSFile *uploadInfo, NSError *error) { if (error) { NSLog(@"Upload image failed: %@", [error localizedDescription]); person.synced = [NSNumber numberWithBool:NO]; } else { person.thumbnailId = [uploadInfo fileId]; person.synced = [NSNumber numberWithBool:YES]; [store saveObject:person withCompletionBlock:^(NSArray *objects, NSError *error) { if (error) { NSLog(@"Saved Failed: %@", [error localizedDescription]); person.synced = [NSNumber numberWithBool:NO]; } else { NSLog(@"Saved Success"); } NSError* errorContext; [defaultManagedObjectContext() save:&errorContext]; } withProgressBlock:nil]; } } progressBlock:nil]; } else { [store saveObject:person withCompletionBlock:^(NSArray *objects, NSError *error) { if (error) { NSLog(@"Saved Failed: %@", [error localizedDescription]); person.synced = [NSNumber numberWithBool:NO]; } else { NSLog(@"Saved Success"); } NSError* errorContext; [defaultManagedObjectContext() save:&errorContext]; } withProgressBlock:nil]; }
Fetching
KCSLinkedAppdataStore* store = [KCSLinkedAppdataStore storeWithCollection:[KCSCollection collectionFromString:@"Person" ofClass:[MOPerson class]] options:nil]; // Load people from the cloud [store queryWithQuery:[KCSQuery query] withCompletionBlock:^(NSArray *objects, NSError *error) { if (error) { NSLog(@"An error occurred on query: %@", error); } else { NSLog(@"Get all people success"); for (MOPerson *person in objects) { if (person.thumbnailId) { [KCSFileStore downloadData:person.thumbnailId completionBlock:^(NSArray *downloadedResources, NSError *error) { if (error == nil) { KCSFile* file = downloadedResources[0]; person.thumbnail = file.data; } else { NSLog(@"Got an error: %@", error); } } progressBlock:nil]; } } } } withProgressBlock:nil];
MOPerson.h and MONotes.h
// MOPerson.h #import <Foundation/Foundation.h> #import <CoreData/CoreData.h> #import <KinveyKit/KinveyKit.h> #import "ModelUtil.h" @class MONotes; NS_ASSUME_NONNULL_BEGIN @interface MOPerson : NSManagedObject <KCSPersistable> @end NS_ASSUME_NONNULL_END #import "MOPerson+CoreDataProperties.h" //MONotes.h #import <Foundation/Foundation.h> #import <CoreData/CoreData.h> #import <KinveyKit/KinveyKit.h> @class MOPerson; NS_ASSUME_NONNULL_BEGIN @interface MONotes : NSManagedObject <KCSPersistable> @end NS_ASSUME_NONNULL_END #import "MONotes+CoreDataProperties.h"
@Pranav any luck?
Would it work better if for saving, do NSManagedObject to NSObject to Kinvey. Then for updating, Kinvey to NSObject to NSManagedObject? I would think this would mitigate any problems that happen for updating because it seems like the Kinvey code is having trouble updating the relational NSManagedObjects. The app needs to be able to persist core data. So using just migrating to Kinvey is not an option.
Brian,
Just wanted to check if you have tried using the onPreSave()/onPostSave() collection hooks for this purpose? So, your app would call a save on the Person (also sending the Notes data along with it). This would first save the Person entity and then call the Person.onPostSave() collection hook. In this code, then you can update the Notes collection with the relevant notes.
In case you are saving the Notes directly and passing the person name to it, you could also implement Notes.OnPreSave() logic and in it - query the Person collection for the person name and find out the person.id, that way you will also persist the person's id in the Notes collection.
I hope I have understood your usecase correctly. If not, please feed me more details. Also let me know if you see any change moving to NSObject.
I will continue reviewing the code in more details and let you know if I have some more comments.
Thanks,
Pranav
Kinvey Support
Thanks Pranav!
How about the updating my NSManagedObject? That's my biggest problem right now.
Hi Brian,
When you debug the app, which is the line that throws the below error?
"CoreData: error: Failed to call designated initializer on NSManagedObject class 'WHATEVER THE CLASS NAME IS’”.
If you could attach a screenshot of the debugger, that would help as I seek help from the engineering team about it.
Secondly, would it be possible for you to share a stripped down version of your Xcode project so that I can straight away use that to reproduce your issue here and seek any further help as needed.
Thanks,
Pranav
Kinvey Support
Where/who can I send the project? The attach a file only lets me attach one file.
Brian
I have two entities, Person and Notes, that have a one to many relationship. They both are NSManagedObjects. I believe I followed everything right from the Data Store and Core Data guides.
The problem: Whenever I try and save a person, it gives me "Reference object does not have ID set". From my understanding, person.notes is what it's referring to. But this should work according to the guides.
The code:
Person.m
Notes.m
Thanks for the help!