I'm not sure if my understanding of Core Data relationships is flawed as I can't seem to achieve what I want to do.
I have a 2 entities created to manage Chat on the app and a one-to-Many relationship between the users and the messages. So a user can have many messages but the messages have just you user (creator).
I am trying to update the ChatUser
entity relationship when a new message is added whereby a connection between the ChatUser
ID and the ChatMessage
is established. I can do this but the issue arises when I go to add a new message to an existing userId
. All that is currently being achieved though is adding an extra userId
into ChatUser
instead of adding only the relationship to the existing UserId
.
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;
// 4 . Get Timestamp for Rippll
float timestamp = @([[NSDate date] timeIntervalSince1970]).floatValue;
NSString * jayID = @"eu-west-1:be6457ce-bac1-412d-9307-e375e52e22ff";
NSString *message = @"Science string!";
// Create a new managed object
ChatUser *chatUserManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
Chat *chatManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatMessage" inManagedObjectContext:context];
Timeline *timelineManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"Timeline" inManagedObjectContext:context];
// 3 . Save Timeline
[timelineManagedObject setEvent:chatEvent];
[timelineManagedObject setTimestamp:[NSNumber numberWithFloat:timestamp]];
[timelineManagedObject setMeta:@""];
[timelineManagedObject setViewed:@NO];
[timelineManagedObject setEventID:jayID];
//Save UserMessage
[chatManagedObject setChatId:jayID];
[chatManagedObject setTimestamp:[NSNumber numberWithFloat:timestamp]];
[chatManagedObject setMessage:message];
[chatManagedObject setMedia:@""];
//Check if value exists
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];
NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];
if (entities.count == 0) {
NSLog(@"GOOD TO ADD");
// no matching object
[chatUserManagedObject setUserId:jayID];
//Create Relationship
[chatUserManagedObject addChatObject:chatManagedObject];
} else {
NSLog(@"IT EXISTS!");
[chatManagedObject setChat:chatUserManagedObject];
}
// Save the object to persistent store
if (![context save:&error]) {
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}
I thin k, @PangHoMing was on the right track, but used Magical Records. Let's do it solely with CD:
First rename the relationships. Probably in ChatMessage
there should be a to-1 relationship named user
(or chatUser
) and in ChatUser
there should be a to-N relationship messages
(or chatMessages
). They should be inverse relationship.
Next you should ask for the existence of a user before creating it. (Otherwise you create phantom users.) You got the code for it:
// Create message as you did
ChatMessage *message = …;
…
// The user will go here
ChatUser *user; // Do not use types in names unless conversion is subject of your code
// Look for an existing one
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"ChatUser"];
[request setPredicate:[NSPredicate predicateWithFormat:@"userId = %@", jayID]];
[request setFetchLimit:1];
NSArray *entities = [[context executeFetchRequest:request error:&error] mutableCopy];
if (entities.count == 0)
{
// Only if there is none, create one
user = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
// Set-up user's properties
…
}
else
{
// Use the existing one
user = entities[0];
}
[message setValue:user forKey:@"user"]; // message.user = user;
As mentioned by others, the inverse relationship is maintained by CD. However, you can use the inverse relationship to add the message, if this is more readable for you:
[[user mutableSetValueForKey:@"messages"] addObject:message]; // [user addMessagesObject:message]
This will maintain the "original" relationship, too.