【问题标题】:RestKit 0.9.3 connectRelationship:withObjectForPrimaryKeyAttribute:RestKit 0.9.3 连接关系:withObjectForPrimaryKeyAttribute:
【发布时间】:2023-03-05 16:12:01
【问题描述】:

我正在尝试使用来自新 RestKit 0.9.3 的示例 RKCatalog。 在 RKRelationshipMappingExample 中,创建者忘记在 Task 和 User 之间添加连接代码,但即使添加后也无法正常工作。

{"project": {
    "id": 123,
    "name": "Produce RestKit Sample Code",
    "description": "We need more sample code!",
    "user": {
        "id": 1,
        "name": "Blake Watters",
        "email": "blake@twotoasters.com"
    },
    "tasks": [
        {"id": 1, "name": "Identify samples to write", "assigned_user_id": 1},
        {"id": 2, "name": "Write the code", "assigned_user_id": 1},
        {"id": 3, "name": "Push to Github", "assigned_user_id": 1},
        {"id": 4, "name": "Update the mailing list", "assigned_user_id": 1}
    ]
}}

[taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:gRKCatalogBaseURL];
        objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"RKRelationshipMappingExample.sqlite"];

        RKManagedObjectMapping* taskMapping = [RKManagedObjectMapping mappingForClass:[Task class]];
        [taskMapping mapKeyPath:@"id" toAttribute:@"taskID"];
        [taskMapping setPrimaryKeyAttribute:@"taskID"];
        [taskMapping mapKeyPath:@"name" toAttribute:@"name"];
        [taskMapping mapKeyPath:@"assigned_user_id" toAttribute:@"assignedUserID"];
        [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];
        [objectManager.mappingProvider setMapping:taskMapping forKeyPath:@"task"];

        RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
        [userMapping mapAttributes:@"name", @"email", nil];
        [userMapping mapKeyPath:@"id" toAttribute:@"userID"];
        [userMapping setPrimaryKeyAttribute:@"userID"];
        [userMapping mapRelationship:@"tasks" withMapping:taskMapping];
        [objectManager.mappingProvider setMapping:userMapping forKeyPath:@"user"];

        // NOTE - Project is not backed by Core Data
        RKObjectMapping* projectMapping = [RKObjectMapping mappingForClass:[Project class]];
        [projectMapping mapKeyPath:@"id" toAttribute:@"projectID"];
        [projectMapping mapAttributes:@"name", @"description", nil];
        [projectMapping mapRelationship:@"user" withMapping:userMapping];
        [projectMapping mapRelationship:@"tasks" withMapping:taskMapping];
        [objectManager.mappingProvider setMapping:projectMapping forKeyPath:@"project"];
    }

    return self;
}

我做的一切都好吗? -- 它不会通过用户 ID 将任务连接到用户。

【问题讨论】:

    标签: objective-c restkit


    【解决方案1】:

    更新:我应该更仔细地阅读Blake's linked post——它会更快地将我指向开发分支。

    底线:一对多映射问题(在 User 对象的 tasks 的反向水合的上下文中讨论)在 0.9.3 中被破坏。截至 2012 年 3 月 8 日,开发分支的拉动确认该问题已在此处解决——布莱克在问题 #284 中解决了该问题。您确实仍然需要添加示例不包含的connectRelationship:withObjectForPrimaryKeyAttribute: 逻辑。


    @Evan,感谢RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace) 的提示——它有助于分析实际发生​​的情况。

    我仍然处于 RestKit 的“寻找我的方式”阶段,所以 YMMV。但是,根据this post by Blake 的说法,实际上看起来你需要两者——这是我可以让示例工作的唯一方法。但是,对相关对象的主键的引用是使用它的本地[即任务的 ivar] 属性来引用的:

            RKManagedObjectMapping* taskMapping = [RKManagedObjectMapping mappingForClass:[Task class]];
            [taskMapping mapKeyPath:@"id" toAttribute:@"taskID"];
            [taskMapping mapKeyPath:@"name" toAttribute:@"name"];
            [taskMapping mapKeyPath:@"assigned_user_id" toAttribute:@"assignedUserID"];
            taskMapping.primaryKeyAttribute = @"taskID";
    
            RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
            [userMapping mapAttributes:@"name", @"email", nil];
            [userMapping mapKeyPath:@"id" toAttribute:@"userID"];
            [userMapping mapRelationship:@"tasks" withMapping:taskMapping];
            userMapping.primaryKeyAttribute = @"userID";
            [objectManager.mappingProvider setMapping:userMapping forKeyPath:@"user"];
    
            [taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];
            [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];
            [objectManager.mappingProvider setMapping:taskMapping forKeyPath:@"task"]; 
    

    这是在大约 3 天前从 master 拉取的。

    【讨论】:

    • 这个答案正确地将用户添加到任务中,但没有将任务添加到用户中。迭代项目现在可以正确显示任务的用户名。但是,无法迭代给定用户的任务。
    【解决方案2】:

    用户->任务映射是在userMapping上设置的,行[userMapping mapRelationship:@"tasks" withMapping:taskMapping];。我假设您是在说没有创建逆?

    如果这是问题所在,我想你会发现 this commit 解决了这个问题,尽管我自己还没有尝试过。 (您可以在此时拉出树,或者更好地拉出当前的主分支)。

    除此之外,[taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"]; 行有问题,它正在搜索主键属性为“assignedUserID”的对象,但查看其他映射,不存在这样的对象。请注意,在 userMapping 上,主键由 [userMapping setPrimaryKeyAttribute:@"userID"]; 定义

    你可能想要[taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"userID"];,或者更好的[taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];

    (通过我链接的提交,我什至不确定是否有必要添加任何东西来获得相反的结果 - 你可以同时尝试看看。)

    如果仍有问题,您可以使用 RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace); 为 ObjectMapper 打开日志

    【讨论】:

      【解决方案3】:

      我一直在弄乱这段代码将近一个半小时,终于让它工作了。我采取的步骤: 1)重新排列关系的创建,如下所示 2) 取消选中 RKRelationshipMappingExample.xcdatamodel > task.assignedUser 关系的“可选”复选标记。我注意到它既是“可选”又是最小 1,最大 1。我在此更改后删除了应用程序并重新安装它。现在用户被添加到任务和任务到用户!

      - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
          self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
          if (self) {
              RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:gRKCatalogBaseURL];
              objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"RKRelationshipMappingExample.sqlite"];
      
      
              RKManagedObjectMapping* taskMapping = [RKManagedObjectMapping mappingForClass:[Task class]];
              [taskMapping mapKeyPath:@"id" toAttribute:@"taskID"];
              [taskMapping mapKeyPath:@"name" toAttribute:@"name"];
              [taskMapping mapKeyPath:@"assigned_user_id" toAttribute:@"assignedUserID"];
              taskMapping.primaryKeyAttribute = @"taskID";
      
              RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];
              [userMapping mapAttributes:@"name", @"email", nil];
              [userMapping mapKeyPath:@"id" toAttribute:@"userID"];
      
              userMapping.primaryKeyAttribute = @"userID";
              [objectManager.mappingProvider setMapping:userMapping forKeyPath:@"user"];
              [objectManager.mappingProvider setMapping:taskMapping forKeyPath:@"task"];
      
              [userMapping mapRelationship:@"tasks" withMapping:taskMapping];        
              [taskMapping mapRelationship:@"assignedUser" withMapping:userMapping];
      
              [taskMapping connectRelationship:@"assignedUser" withObjectForPrimaryKeyAttribute:@"assignedUserID"];
      
      
              // NOTE - Project is not backed by Core Data
              RKObjectMapping* projectMapping = [RKObjectMapping mappingForClass:[Project class]];
              [projectMapping mapKeyPath:@"id" toAttribute:@"projectID"];
              [projectMapping mapAttributes:@"name", @"description", nil];
              [projectMapping mapRelationship:@"user" withMapping:userMapping];
              [projectMapping mapRelationship:@"tasks" withMapping:taskMapping];
              [objectManager.mappingProvider setMapping:projectMapping forKeyPath:@"project"];
      
      
      
          }
      
          return self;
      }
      
      //to see NSLog messages, change the LOGGER_DEBUG to 2 (in LoggerClient.m) like this:
      #define LOGGER_DEBUG 2
      #ifdef NSLog
          #undef NSLog
      #endif
      
      
      
      //test method to make sure all relationships are created.
      - (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
          _objects = [objects retain];
      
          for(Project* managedObject in objects)
          {   NSLog(@" project user: %@", [managedObject.user description]);
              NSLog(@"###### user tasks count: %i",[managedObject.user.tasks  count]);
              for(Task* task in managedObject.user.tasks)
              {
                  NSLog(@"+++++managedObject.user.tasks: %@", [task description]);
              }
      
              for(Task* task in managedObject.tasks)
              {
                  NSLog(@"*****task: %@", [task description]);
              }
      
          }
          [self.tableView reloadData];
      }
      

      【讨论】:

      • 很好地抓住了核心数据属性——在看到您对我的帖子的评论后,我正在研究同样的问题,认为它必须与实体之间的关系有关。尝试同时学习 RestKit 和 Core Data 有点挑战!顺便说一句,不需要重新排列代码。
      • 嗯——不幸的是,这看起来比现在更有希望。第一次在全新安装上正确加载水合物对象图,但随后的调用显示 user.tasks NSSet 的相同关系错误。我在 Task 实体的 assignedUser 的“可选”标志上打开和关闭了很多次,但我无法获得可重复的正确行为。
      • 已确认——语句顺序和可选标志与此问题无关——请参阅我的更新答案
      猜你喜欢
      • 2014-05-12
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多