向现有核心数据实体关系添加新属性
Add new attribute to existing Core Data Entity Relationship
我不确定我对核心数据关系的理解是否有缺陷,因为我似乎无法实现我想做的事情。
我创建了 2 个实体来管理应用程序上的聊天以及用户和消息之间的一对多关系。所以一个用户可以有很多消息,但消息只有你用户(创建者)。
我正在尝试在添加新消息时更新 ChatUser
实体关系,从而在 ChatUser
ID 和 ChatMessage
之间建立连接。我可以这样做,但是当我向现有 userId
添加新消息时出现问题。目前正在实现的是在 ChatUser
中添加一个额外的 userId
,而不是仅添加与现有 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]);
}
- 您应该首先检查您的上下文中是否已经存在 ChatUser 实体。只需尝试获取具有该用户 ID 的 ChatUser,如果有 ChatUser return,则意味着 ChatUser 已被创建;如果它 return 为 nil,则表示没有正在创建该用户 ID 的 ChatUser 实体。
- 要处理 1-many 关系,您应该使用 [message setChatUser:chatUser] 而不是 chatUser addMessageObject
如有任何后续问题,请随时提出。干杯!
一旦您从任一方向启动关系,Core Data 将自动管理关系的另一端。您可以添加到 ChatUser
的 chat
集合或使用 NSManagedObject
的实例设置 ChatMessage
的 chat
,这就是您所要做的。请注意,此过程不需要您管理外键,复杂性已从您那里抽象出来。如果服务器端 ID 可以帮助您与 API 交互,您仍然可以存储服务器端 ID,但 Core Data 不需要它们。
我建议更改关系的一端,这样两者就不会被命名为同一事物。考虑将 ChatUser
的关系更新为 messages
或类似的关系。
我觉得k,@PangHoMing走对了路,但是用的是Magical Records。让我们只用 CD 来做:
首先重命名关系。可能在 ChatMessage
中应该有一个名为 user
(或 chatUser
)的 to-1 关系,在 ChatUser
中应该有一个 to-N 关系 messages
(或 chatMessages
)。他们应该是反比关系。
接下来您应该在创建用户之前询问用户是否存在。 (否则你会创建幻影用户。)你得到了它的代码:
// 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;
正如其他人所说,反向关系是由CD维持的。但是,您可以使用反向关系来添加消息,如果这对您来说更具可读性:
[[user mutableSetValueForKey:@"messages"] addObject:message]; // [user addMessagesObject:message]
这也将维持 "original" 关系。
尝试实现类似这样的东西。这个方案和Amin Negm-Awad
提出的几乎一样
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]);
}
我不确定我对核心数据关系的理解是否有缺陷,因为我似乎无法实现我想做的事情。
我创建了 2 个实体来管理应用程序上的聊天以及用户和消息之间的一对多关系。所以一个用户可以有很多消息,但消息只有你用户(创建者)。
我正在尝试在添加新消息时更新 ChatUser
实体关系,从而在 ChatUser
ID 和 ChatMessage
之间建立连接。我可以这样做,但是当我向现有 userId
添加新消息时出现问题。目前正在实现的是在 ChatUser
中添加一个额外的 userId
,而不是仅添加与现有 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]);
}
- 您应该首先检查您的上下文中是否已经存在 ChatUser 实体。只需尝试获取具有该用户 ID 的 ChatUser,如果有 ChatUser return,则意味着 ChatUser 已被创建;如果它 return 为 nil,则表示没有正在创建该用户 ID 的 ChatUser 实体。
- 要处理 1-many 关系,您应该使用 [message setChatUser:chatUser] 而不是 chatUser addMessageObject
如有任何后续问题,请随时提出。干杯!
一旦您从任一方向启动关系,Core Data 将自动管理关系的另一端。您可以添加到 ChatUser
的 chat
集合或使用 NSManagedObject
的实例设置 ChatMessage
的 chat
,这就是您所要做的。请注意,此过程不需要您管理外键,复杂性已从您那里抽象出来。如果服务器端 ID 可以帮助您与 API 交互,您仍然可以存储服务器端 ID,但 Core Data 不需要它们。
我建议更改关系的一端,这样两者就不会被命名为同一事物。考虑将 ChatUser
的关系更新为 messages
或类似的关系。
我觉得k,@PangHoMing走对了路,但是用的是Magical Records。让我们只用 CD 来做:
首先重命名关系。可能在 ChatMessage
中应该有一个名为 user
(或 chatUser
)的 to-1 关系,在 ChatUser
中应该有一个 to-N 关系 messages
(或 chatMessages
)。他们应该是反比关系。
接下来您应该在创建用户之前询问用户是否存在。 (否则你会创建幻影用户。)你得到了它的代码:
// 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;
正如其他人所说,反向关系是由CD维持的。但是,您可以使用反向关系来添加消息,如果这对您来说更具可读性:
[[user mutableSetValueForKey:@"messages"] addObject:message]; // [user addMessagesObject:message]
这也将维持 "original" 关系。
尝试实现类似这样的东西。这个方案和Amin Negm-Awad
提出的几乎一样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]);
}