2013-09-21 176 views
8

當JSON響應僅包含主鍵而不是完全嵌套的數組來創建新對象時,我在映射關係時遇到問題。使用主鍵的RestKit關係映射

我有2個類 - 商店和項目,正如你所期望的商店 - >項目有一對多的關係。

我有一個商店(和項目)的本地核心數據存儲,每個都有一個主鍵。然後,我希望下載一個物品列表作爲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 
}, 
... 

這裏是我的代碼的時刻。

AppDelegate.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)]]; 

... 

ItemsTableViewController.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]; 
} 

編輯: 韋恩,我有這在應用程序代理相關的地方,但得到的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]; 

NSException

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

有什麼我錯過了?

回答

5

您需要爲項目添加一個瞬態屬性(稱爲shopId)和一個關聯的映射。

配置使用外鍵映射的關係:

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

然後使用addConnection:將其添加到您的映射。

+0

謝謝@Wain。這段代碼是在App Delegate還是View Controller? Andy – Andy

+0

將它添加到'itemMapping'中,您之前曾嘗試添加關係映射(但是對於嵌套項目)。 – Wain

+0

我收到一個異常 - 請參閱編輯。這是因爲我沒有創建項目的瞬態屬性?如果是這樣如何?安迪 – Andy