Добавить новый атрибут к существующим отношениям данных ядра
Я не уверен, что мое понимание взаимоотношений с основными данными ошибочно, поскольку я не могу достичь того, что я хочу сделать.
У меня есть 2 объекта, созданных для управления чатом в приложении и отношения "один ко многим" между пользователями и сообщениями. Таким образом, пользователь может иметь много сообщений, но сообщения имеют только пользователь (создатель).
![enter image description here]()
Я пытаюсь обновить отношение сущности ChatUser
при добавлении нового сообщения, в результате чего устанавливается соединение между идентификатором ChatUser
и ChatMessage
. Я могу это сделать, но проблема возникает, когда я иду добавить новое сообщение в существующий userId
. Все, что в настоящее время достигается, добавляет дополнительный userId
в ChatUser
вместо добавления только отношения к существующей 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]);
}
Ответы
Ответ 1
Я тонкий k, @PangHoMing был на правильном пути, но использовал Magical Records. Позвольте делать это исключительно с CD:
Сначала переименуйте отношения. Вероятно, в ChatMessage
должно быть отношение to-1 с именем user
(или chatUser
), а в chatUser
должно быть отношение to-N messages
(или chatMessages
). Они должны быть обратными отношениями.
Затем вы должны спросить о существовании пользователя перед его созданием. (В противном случае вы создаете пользователей phantom.) У вас есть код для него:
// 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 properties
…
}
else
{
// Use the existing one
user = entities[0];
}
[message setValue:user forKey:@"user"]; // message.user = user;
Как упоминалось другими, обратная связь поддерживается CD. Однако вы можете использовать обратную связь для добавления сообщения, если это более читаемо для вас:
[[user mutableSetValueForKey:@"messages"] addObject:message]; // [user addMessagesObject:message]
Это также будет поддерживать "оригинальные" отношения.
Ответ 2
Основные данные автоматически управляют другим концом отношения после того, как вы начнете его с любого направления. Вы можете либо добавить в коллекцию ChatUser
chat
, либо установить ChatMessage
chat
с экземпляром NSManagedObject
и все, что вам нужно сделать. Обратите внимание, что этот процесс не требует от вас управления внешними ключами, эта сложность абстрагируется от вас. Вы все равно можете хранить идентификаторы на стороне сервера, если они помогают вам взаимодействовать с API, но они не требуются для Core Data.
Я бы порекомендовал изменить один конец отношения, так что оба они не называются одинаковыми. Рассмотрите обновление отношения ChatUser
как messages
или что-то подобное.
Ответ 3
- Сначала вы должны проверить, существует ли объект ChatUser уже в вашем Контексте. Просто, пытаясь получить ChatUser с этим userId, если есть возврат ChatUser, означающий, что ChatUser уже был разбит; если он возвращает nil, это означает, что не существует объекта ChatUser с созданным пользователем.
- Чтобы обрабатывать отношение 1 - много, вы должны использовать [message setChatUser: chatUser] вместо chatUser addMessageObject
Не стесняйтесь задавать любые последующие вопросы, если у вас есть. Ура!
Ответ 4
Попробуйте реализовать что-то вроде этого. Это решение почти такое же, как предложенный Амином Негм-Авадом
NSManagedObjectContext *context = [self managedObjectContext];
NSError *error = nil;
// 4 . Get Timestamp for Rippll
NSString * jayID = @"eu-west-1:be6457ce-bac1-412d-9307-e375e52e22ff";
NSString *message = @"Science string!";
//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];
ChatUser *chatUserManagedObject = nil;
if (entities.count)
{
NSLog(@"IT EXISTS!");
chatUserManagedObject = entities.firstObject;
}
else
{
NSLog(@"GOOD TO ADD");
chatUserManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatUser" inManagedObjectContext:context];
[chatUserManagedObject setUserId:jayID];
}
// Create a new managed object
Chat *chatManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"ChatMessage" inManagedObjectContext:context];
//Save UserMessage
[chatManagedObject setChatId:jayID];
[chatManagedObject setTimestamp:[NSDate date]];
[chatManagedObject setMessage:message];
[chatManagedObject setMedia:@""];
[chatUserManagedObject addChatObject:chatManagedObject];
// Save the object to persistent store
if (![context save:&error]) {
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}