Start a new topic

Relational Data Reference ID

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

 

- (NSDictionary *)hostToKinveyPropertyMapping {
    return @{
             @"entityId" : KCSEntityKeyId, //the required _id field
             //@"objectID" : @"objectID",
             //@"meta" : KCSEntityKeyMetadata,
             @"name" : @"name",
             @"initials" : @"initials",
             @"notes" : @"notes",
             };
}

+ (NSDictionary *)kinveyPropertyToCollectionMapping {
    return @{
             @"notes" : @"Notes",
             };
}

+(NSDictionary *)kinveyObjectBuilderOptions {
    // reference class map - maps properties to objects
    return @{ KCS_USE_DESIGNATED_INITIALIZER_MAPPING_KEY : @YES,
              KCS_REFERENCE_MAP_KEY : @{
                                        @"notes" : [MONotes class],
                                        }
              };
}

- (NSArray *)referenceKinveyPropertiesOfObjectsToSave {
    return @[ @"notes"];
}

+ (id)kinveyDesignatedInitializer:(NSDictionary *)jsonDocument
{
    NSString* existingID = jsonDocument[KCSEntityKeyId];
    id obj = nil;
    NSManagedObjectContext* context = defaultManagedObjectContext();
    NSEntityDescription* entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
    
    if (existingID) {
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:entity];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entityId = %@", existingID];
        [request setPredicate:predicate];
        NSArray* results = [context executeFetchRequest:request error:NULL];
        if (results != nil && results.count > 0) {
            obj = results[0];
        }
    }
    
    if (obj == nil) {
        //fall back to creating a new if one if there is an error, or if it is new
        obj = [[MOPerson alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
    }
    
    return obj;
}

 

Notes.m

 

- (NSDictionary *)hostToKinveyPropertyMapping {
    return @{
             @"entityId" : KCSEntityKeyId, //the required _id field
             //@"meta" : KCSEntityKeyMetadata, //meta maps to metadata
             @"dateAdded" : @"dateAdded",
             @"text" : @"text",
             @"person" : @"person"
             };
}

+ (NSDictionary *)kinveyPropertyToCollectionMapping
{
    return @{@"person" : @"Person"};
}

+(NSDictionary *)kinveyObjectBuilderOptions {
    // reference class map - maps properties to objects
    return @{ KCS_USE_DESIGNATED_INITIALIZER_MAPPING_KEY : @YES,
              KCS_REFERENCE_MAP_KEY : @{@"person" : [MOPerson class]
                                        }
              };
}

+ (id)kinveyDesignatedInitializer:(NSDictionary *)jsonDocument
{
    NSString* existingID = jsonDocument[KCSEntityKeyId];
    id obj = nil;
    NSManagedObjectContext* context = defaultManagedObjectContext();
    NSEntityDescription* entity = [NSEntityDescription entityForName:@"Notes" inManagedObjectContext:context];
    
    if (existingID) {
        NSFetchRequest *request = [[NSFetchRequest alloc] init];
        [request setEntity:entity];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"entityId = %@", existingID];
        [request setPredicate:predicate];
        NSArray* results = [context executeFetchRequest:request error:NULL];
        if (results != nil && results.count > 0) {
            obj = results[0];
        }
    }
    
    if (obj == nil) {
        //fall back to creating a new if one if there is an error, or if it is new
        obj = [[MONotes alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
    }
    
    return obj;
}

 

Thanks for the help!


Unfortunately not due to the fact that we are trying to reduce as much data used as possible. One theory is having a default value and then deleting it once it's successfully saved. But I'm querying all the data to update it and then I would have to iterate through all the data and delete each oneToOne entity that equals the default value.

Brian,

Is there any default value that you can send? If you send some default, does it make a difference?

Thanks,
Pranav

 

Pranav,


Same issue as the initial problem. But it now works for one to many relationships. If add a one to one relationships it gives me: CoreData: error: Failed to call designated initializer on NSManagedObject class (was doing this for one to many relationships before the update).


 Snippet in onPostFetch:  

for (var i = 0; i < count; i++) {
    //oneToOne is the entity
    response.body[i].oneToOne = nil; // Try number 1, didn't like setting nil to the oneToOne for CoreData. Gave the same error in CoreData if I didn't change it.
    response.body[i].oneToOne = []; // Try number 2, array can't initialize oneToOne from NSArray
}

  

Not sure what to make oneToOne if it's nil or there's nothing.

Brian,

Please give me little more details of the issue that you are facing and also the snippets that you have tried in Pre/Post collection hooks?

 

Thanks,

Pranav

Kinvey Support

Everything seems to be working except for fetching one to one relationships. If one entity is null, it cannot initialize the NSManagedObject. I've tried different ways of removing the null object in collection hooks, but Kinvey SDK still wants to initialize the object. I'm guessing it has to deal with - (NSDictionary *)hostToKinveyPropertyMapping; ?

Brian,


Can you please try with the latest iOS SDK and see if it works for you http://devcenter.kinvey.com/ios/downloads?


Thanks,

Pranav

Kinvey Support

Pranav,


Any progress or, hopefully, success?


Thanks,

Brian

Brian,

Just wanted to let you know that this has been forwarded to the engineering for them to look further.

Will let you know as soon as I have more information.

Thanks,
Pranav

Kinvey Support

Pranav,


That is correct. I am also getting the same crash.

Hi Brian,

I tried executing your app and I’m consistently getting the following crash:



Just wanted to confirm with you that you are also seeing the same thing.

Thanks,
Pranav
Kinvey Support

 

Brian,

Received it. I will let you know if there are any questions.

Thanks,
Pranav
Kinvey Support

 

Brian,

You can zip up the code and send it to pranav@kinvey.com or "trinitypranav" is my github account.

Also let me know the kid and the name of your app.

Thanks,
Pranav
Kinvey Support

 

Brian,


Please send the code to pranav@kinvey.com.


If you can add support@kinvey.com as a collaborator to the app in the backend that’ll be great.


Also let me know the kid and the name of your app.


Thanks,

Pranav

Kinvey Support

Where/who can I send the project? The attach a file only lets me attach one file.

 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

Login or Signup to post a comment