2014-01-29 56 views
3

請指導我關於以下問題。RestKit添加屬性映射和關係映射

我有兩個實體的關係如圖下圖 enter image description here

我使用最新版本的RestKit的與iOS 7

現在在我的appDelegate我使用下面的映射「列表」實體

NSDictionary *listObjectMapping = @{ 
             @"listID" : @"listID", 
             @"listName" : @"listName", 
             @"listSyncStatus" : @"listSyncStatus" 
           }; 

RKEntityMapping *listEntityMapping = [RKEntityMapping mappingForEntityForName:@"List" inManagedObjectStore:managedObjectStore]; 
[listEntityMapping addAttributeMappingsFromDictionary:listObjectMapping]; 

listEntityMapping.identificationAttributes = @[ @"listID" ]; 

RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:listEntityMapping 
                         method:RKRequestMethodGET 
                        pathPattern:@"/api/lists" 
                         keyPath:nil 
                        statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; 
[objectManager addResponseDescriptor:responseDescriptor]; 


//Inverse mapping, to perform a POST 
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[listEntityMapping inverseMapping] 
                       objectClass:[List class] 
                       rootKeyPath:nil 
                        method:RKRequestMethodPOST]; 
objectManager.requestSerializationMIMEType = RKMIMETypeJSON; 
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON]; 

[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/json"]; 
[objectManager addRequestDescriptor:requestDescriptor]; 



//Inverse mapping, to perform a PUT 
requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[listEntityMapping inverseMapping] 
                       objectClass:[List class] 
                       rootKeyPath:nil 
                        method:RKRequestMethodPUT]; 
objectManager.requestSerializationMIMEType = RKMIMETypeJSON; 
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON]; 

[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/json"]; 
[objectManager addRequestDescriptor:requestDescriptor]; 

,並使用下面的映射爲我的任務對象

NSDictionary *taskObjectMapping = @{ 
            @"listID" : @"listID", 
            @"taskID" : @"taskID", 
            @"taskName" : @"taskName", 
            @"taskCompletionStatus" : @"taskCompletionStatus", 
            @"taskSyncStatus" : @"taskSyncStatus" 
           }; 

RKEntityMapping *taskEntityMapping = [RKEntityMapping mappingForEntityForName:@"Task" inManagedObjectStore:managedObjectStore]; 
[taskEntityMapping addAttributeMappingsFromDictionary:taskObjectMapping]; 
taskEntityMapping.identificationAttributes = @[ @"taskID" ]; 


RKResponseDescriptor *taskResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:taskEntityMapping 
                          method:RKRequestMethodGET 
                         pathPattern:@"/api/list/:id" 
                          keyPath:nil 
                         statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]; 
[objectManager addResponseDescriptor:taskResponseDescriptor]; 


//Inverse mapping, to perform a POST 
RKRequestDescriptor *taskRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[taskEntityMapping inverseMapping] 
                       objectClass:[Task class] 
                       rootKeyPath:nil 
                        method:RKRequestMethodPOST]; 
objectManager.requestSerializationMIMEType = RKMIMETypeJSON; 
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON]; 
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/json"]; 
[objectManager addRequestDescriptor:taskRequestDescriptor]; 



//Inverse mapping, to perform a PUT 
taskRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[taskEntityMapping inverseMapping] 
                  objectClass:[Task class] 
                  rootKeyPath:nil 
                   method:RKRequestMethodPUT]; 
objectManager.requestSerializationMIMEType = RKMIMETypeJSON; 
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON]; 
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/json"]; 
[objectManager addRequestDescriptor:taskRequestDescriptor]; 

現在我的問題是如何在這兩個實體之間添加關係映射? 什麼是正確的方法?

如果我使用我使用的代碼

[taskEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"list.listID" 
                        toKeyPath:@"listID" 
                       withMapping:listEntityMapping]]; 

一個運行時錯誤時說:「無法添加映射的keyPath listID,已經存在一個

,如果我用這個

以下行
[listEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"listID" 
                         toKeyPath:@"list.listID" 
                        withMapping:taskEntityMapping]]; 

應用程序與此錯誤崩潰實體列表不是關鍵值編碼兼容t他關鍵的「名單」。

,如果我省略上面的代碼,並嘗試從關係

task.list.listID 

得到listID它給了我「0」。任何人都可以告訴我到底我做錯了什麼,或者我應該怎麼做才能完成上述任務。如果需要,我可以提供更多細節。

編輯

,但我請求所有列表返回以下JSON

GET www.mydomain.com/api/lists 

[ 
{"listID":"42","listName":"List 4","listSyncStatus":"1"}, 
{"listID":"41","listName":"List 3","listSyncStatus":"1"}, 
{"listID":"40","listName":"List 2","listSyncStatus":"1"} 
] 

,並要求單獨的列表如下

GET www.mydomain.com/api/list/42 
[ 
{"taskID":"22","listID":"42","taskName":"Task 2","taskSyncStatus":"1","taskCompletionStatus":"1"}, 

{"taskID":"21","listID":"42","taskName":"Task 1","taskSyncStatus":"1","taskCompletionStatus":"1"} 
] 

即會返回其任務是沒有級聯關係在json中返回。這是錯誤的方式還是我在這裏失蹤?

更正接受答案

後,事實證明我是錯了返回JSON即返回的JSON中沒有任何關係,而iOS的模式有關係「任務」,所以我編輯我的REST API返回正確的嵌套JSON是像下面

[ { "listID" : "96", 
    "listName" : "List 1", 
    "listSyncStatus" : "1", 
    "tasks" : [ { "taskCompletionStatus" : "1", 
      "taskID" : "67", 
      "taskName" : "Task 2", 
      "taskSyncStatus" : "1" 
     }, 
     { "taskCompletionStatus" : "1", 
      "taskID" : "66", 
      "taskName" : "Task 1", 
      "taskSyncStatus" : "1" 
     } 
     ] 
    }, 
    { "listID" : "97", 
    "listName" : "List 2", 
    "listSyncStatus" : "1", 
    "tasks" : [ { "taskCompletionStatus" : "1", 
      "taskID" : "69", 
      "taskName" : "Task 1", 
      "taskSyncStatus" : "1" 
     }, 
     { "taskCompletionStatus" : "1", 
      "taskID" : "68", 
      "taskName" : "Task 1", 
      "taskSyncStatus" : "1" 
     } 
     ] 
    } 
] 

以上的嵌套JSON回來後,一切正常般的魅力,特別是這條線

[listEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"tasks" 
                        toKeyPath:@"tasks" 
                       withMapping:taskEntityMapping]]; 

希望這有助於把握像我這樣的人的關係概念。

回答

5

您模式圖顯示,你有一個一對多關係(一個列表有許多任務)。

據我所知,在這種情況下,你需要在列表添加映射關係只實體,在任務實體沒有必要。也爲一對多關係,您不需要在Task實體下添加list關係。

你的實體關係應該是這樣的

enter image description here

因此,嘗試以下

[listEntityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"YOUR_JSON_KEYPATH_HERE" toKeyPath:@"tasks" withMapping: taskEntityMapping]]; 

重要

在上述方法

FromKeyPath parameter應該是您的關係開始的JSON key的名稱。

toKeyPath parameter應該是您在實體圖中提到的relationship name。即; tasks

withMapping應該是許多實體的映射。在你的情況下taskEntityMapping

希望能解決這個問題。

+2

iOS建議應該存在反向關係。 – Umair

+0

@Umair,謝謝你是對的:)。消除反向關係的建議是爲了讓你的代碼儘可能少。所以調試可以很容易。如果事情現在正在運行良好,您可以根據需要添加反比關係。這是我喜歡如何調試我的代碼:) – Khawar

+0

@Khawar很多感謝您的解釋 – gbk

0

不知道爲什麼,這是行不通的,但你可以嘗試建立映射關係是這樣的:

[taskEntityMapping addConnectionForRelationship:@"list" connectedBy:@{ @"listId": @"listId" }]; 
[listEntityMapping addConnectionForRelationship:@"tasks" connectedBy:@{ @"listId":@"listId"}];