代码之家  ›  专栏  ›  技术社区  ›  Andy

RestKit与主键的关系映射

  •  8
  • Andy  · 技术社区  · 13 年前

    当JSON响应只包含主键而不包含用于创建新对象的完全嵌套数组时,我在映射关系时遇到了问题。

    我有两个类-商店和物品,正如你所期望的那样,商店->项具有一对多关系。

    我有一个商店(和物品)的本地核心数据存储,每个商店都有一个主键。然后,我希望以JSON的形式下载一个项目列表,并映射到核心数据实体,但只包括商店的主键,而不是将所有商店的详细信息作为嵌套数组-这将是对网络流量的巨大浪费,因为我正在下载500多个项目的详细信息。

    以下是来自两个请求的JSON:

    /商店

    {
        "id" : 1,
        "shop" : "Shop A",
        "city" : "New York"
    },
    {
        "id" : 2,
        "shop" : "Shop B",
        "city" : "London"
    },
    ...
    

    /项目

    {
        "id" : 1,
        "name" : "Shoes",
        "manufacturer" : "Vans",
        "shopId" : 1
    },
    {
        "id" : 2,
        "name" : "T-shirt",
        "manufacturer" : "Animal",
        "shopId" : 2
    },
    {
        "id" : 3,
        "name" : "Scarf",
        "manufacturer" : "Ted Baker",
        "shopId" : 1
    },
    {
        "id" : 4,
        "name" : "Sunglasses",
        "manufacturer" : "Ray-Ban",
        "shopId" : 3
    },
    ...
    

    这是我现在的密码。

    应用程序委派.m

    ...
    
    NSURL *baseURL = [NSURL URLWithString:@"http://localhost/company/API"];
    RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
    
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
    
    [objectManager.HTTPClient setDefaultHeader:@"Accept" value:@"application/json"];
    
    NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
    objectManager.managedObjectStore = managedObjectStore;
    
    // Shop Mapping
    
    RKEntityMapping *shopMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Shop class])
                                                           inManagedObjectStore:objectManager.managedObjectStore];
    NSDictionary *shopMappingAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"objectId",@"id",@"name",@"shop",@"city",@"city",nil];
    shopMapping.identificationAttributes = @[@"objectId"];
    [shopMapping addAttributeMappingsFromDictionary:shopMappingAttributes];
    [objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:shopMapping
                                                                                 pathPattern:@"/shops"
                                                                                     keyPath:nil
                                                                                 statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
    
    
    // Item Mapping
    
    RKEntityMapping *itemMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Item class])
                                                           inManagedObjectStore:objectManager.managedObjectStore];
    NSDictionary *itemMappingAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"objectId",@"id",@"name", @"name",@"manufacturer",@"manufacturer",nil];
    itemMapping.identificationAttributes = @[@"objectId"];
    [itemMapping addAttributeMappingsFromDictionary:itemMappingAttributes];
    
    // Define the relationship mapping
    
    [objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:itemMapping
                                                                                 pathPattern:@"/items"
                                                                                     keyPath:nil
                                                                                 statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
    
    ...
    

    项目TableViewController.m

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        // Update Shops
        [[RKObjectManager sharedManager] getObjectsAtPath:@"/shops"
                                           parameters:nil
                                              success:nil
                                              failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                                  NSLog(@"Error: %@",error);
                                              }];
    
        // Update/Get Items
        NSDictionary *parameters = @{
                                 @"username": self.username,
                                 @"password": self.password,
                                 @"API_key": @"abc123",
                                 };
    
        NSMutableURLRequest *request = [[RKObjectManager sharedManager] requestWithObject:nil
                                                                               method:RKRequestMethodPOST
                                                                                 path:@"/items"
                                                                           parameters:parameters];
    
        RKManagedObjectRequestOperation *operation = [[RKObjectManager sharedManager] managedObjectRequestOperationWithRequest:request managedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext
                                                                      success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                                                                          Item *item = [mappingResult firstObject];
                                                                          NSLog(@"Mapped the Item: %@", item);
                                                                      } failure:^(RKObjectRequestOperation *operation, NSError *error) {
                                                                          NSLog(@"Error: %@",error);
                                                                      }];
        NSOperationQueue *operationQueue = [NSOperationQueue new];
        [operationQueue addOperation:operation];
    }
    

    编辑: Wain,我在应用程序代理的相关位置有这个,但得到了NSException

    NSEntityDescription *itemEntity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:managedObjectStore.mainQueueManagedObjectContext];
    NSRelationshipDescription *shopRelationship = [itemEntity relationshipsByName][@"shop"];
    RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:shopRelationship attributes:@{ @"shopId": @"objectId" }];
    [itemMapping addConnection:connection];
    

    NSE例外

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Item''
    

    我错过了什么?

    1 回复  |  直到 12 年前
        1
  •  5
  •   Wain    13 年前

    您需要向项添加一个临时属性(称为 shopId )以及相关联的映射。

    使用外键映射将关系配置为:

    NSEntityDescription *itemEntity = [NSEntityDescription entityForName:@"Item" inManagedObjectContext:managedObjectContext];
    NSRelationshipDescription *shopRelationship = [itemEntity relationshipsByName][@"shop"];
    RKConnectionDescription *connection = [[RKConnectionDescription alloc] initWithRelationship:shopRelationship attributes:@{ @"shopId": @"id" }];
    

    然后使用 addConnection: 将其添加到映射中。