【问题标题】:Add new attribute to existing Core Data Entity Relationship向现有核心数据实体关系添加新属性
【发布时间】:2015-06-17 12:14:42
【问题描述】:

我不确定我对核心数据关系的理解是否存在缺陷,因为我似乎无法实现我想做的事情。

我创建了 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]);
}

【问题讨论】:

  • 如果 'chat' 是您从消息到用户的反向关系,那么您需要做的就是将用户对象分配给聊天消息对象的聊天属性,Core Data 会处理给你。
  • @Paulw11 那么核心数据如何知道它所关联的值呢?
  • @Paulw11 这不是我对chatUserManagedObject.userId = jayID; 所做的吗?
  • 不,你没有分配对象的“id”,你分配的是实际的 NSManagedObject 实例
  • 另一件似乎令人困惑的事情是您的 id 列(来自您的服务器?)不是 Core Data 用来维护关系连接的。它有自己的 id 和外键列,对我们程序员来说是隐藏的。

标签: ios objective-c core-data nsfetchedresultscontroller nsmanagedobject


【解决方案1】:
  1. 您应该首先检查您的上下文中是否已经存在 ChatUser 实体。只需尝试使用该 userId 获取 ChatUser,如果有 ChatUser 返回,则意味着 ChatUser 已被装箱;如果它返回 nil,则表示没有创建具有该 userId 的 ChatUser 实体。
  2. 要处理 1 - many 关系,您应该使用 [message setChatUser:chatUser] 而不是 chatUser addMessageObject

如有任何后续问题,请随时提出。干杯!

【讨论】:

  • 嗨。你最后的代码没有意义。据我了解,我要设置 NSManaged 对象,这些对象是字符串和 NSmanagedobject 的混合体?
  • 我也没有setChatUser
  • 对不起,我上面的代码是使用 MagicalRecord 框架的代码。你可以看看这个教程,code.tutsplus.com/tutorials/…
  • 我已经看过了。我只是不明白 NSManagedObject 是如何知道它连接到现有用户的。
【解决方案2】:

一旦您从任一方向启动关系,Core Data 将自动管理关系的另一端。您可以添加到ChatUserchat 集合或使用NSManagedObject 的实例设置ChatMessagechat,这就是您所要做的。请注意,此过程不需要您管理外键,复杂性已从您身上抽象出来。如果它们可以帮助您与 API 交互,您仍然可以存储服务器端 ID,但 Core Data 不需要它们。

我建议更改关系的一端,以便两者的名称不同。考虑将ChatUser 的关系更新为messages 或类似的东西。

【讨论】:

  • 我不明白代码有什么问题? ChatUser's chat collection 是什么意思?数据被添加到现有关系中,但这发生在实际调用 nsmanagedobject 的地方
  • 您说“当我向现有用户 ID 添加新消息时出现问题”您能具体说明问题是什么吗?我的印象是,您只是想知道它是如何工作的,而不是遇到特定错误?
【解决方案3】:

我认为 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]

这也将保持“原始”关系。

【讨论】:

    【解决方案4】:

    尝试实现类似的东西。该解决方案与 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]);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-12
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多