我試圖通過RestKit將用戶和組映射到CoreData對象,維護兩者之間的關係。通過ID數組映射關係在RestKit中不起作用
的JSON的用戶是一樣的東西
{"users":
[{"fullname": "John Doe", "_id": "1"}
...
]
}
和JSON的羣體是一樣的東西
{"groups":
[{"name": "John's group", "_id": "a",
"members": ["1", "2"]
...
]
}
我也有相應的核心數據對象,User
和Group
,有一個組與用戶之間的多對一關係映射。 Group
中的關係屬性被稱爲members
,單獨的NSArray
被稱爲memberIDs
包含所有成員用戶的字符串ID數組。
我想在RestKit中完成的是加載這些對象,併爲我映射關係。加載用戶的代碼是直線前進標準的東西,以及加載組的代碼是一樣的東西
RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];
// Create an empty user mapping to handle the relationship mapping
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
[groupMapping hasMany:@"members" withMapping:userMapping];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];
RKObjectRouter* router = objectManager.router;
[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];
當我運行這段代碼,我得到以下警告吐幾次(似乎是約兩倍每關係):
2012-10-24 08:55:10.170 Test[35023:18503] W restkit.core_data.cache:RKEntityByAttributeCache.m:205 Unable to add object with nil value for attribute 'identifier': <User: 0x86f7fc0> (entity: User; id: 0x8652400 <x-coredata:///User/t01A9EDBD-A523-4806-AFC2-9B06873D764E531> ; data: {
fullname = nil;
identifier = nil;
})
奇怪的是,這種關係被設置正確(甚至看着SQLite數據庫,一切看起來不錯有),但我不開心的東西在RestKit顯然會錯代碼,它似乎與我在上面的代碼中創建的虛假用戶映射有關(它是空的,因爲沒有要在ID數組中映射的東西)。
我試過的替代品,例如,當我添加了關鍵路徑映射:
[userMapping mapKeyPath:@"" toAttribute:@"identifier"];
它抱怨,顯然是因爲關鍵路徑是空的
2012-10-24 09:24:11.735 Test[35399:14003] !! Uncaught exception !!
[<__NSCFString 0xa57f460> valueForUndefinedKey:]: this class is not key value coding-compliant for the key .
如果我嘗試使用真正User
映射
[groupMapping hasMany:@"members" withMapping:[[RKObjectManager sharedManager].mappingProvider objectMappingForKeyPath:@"users"]];
我收到以下錯誤
2012-10-24 09:52:49.973 Test[35799:18403] !! Uncaught exception !!
[<__NSCFString 0xa56e9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _id.
2012-10-24 09:52:49.973 Test[35799:18403] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0xa56e9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key _id.'
好像RestKit正試圖在ID字符串本身的memberIDs陣列中映射到User
對象,它們不作任何意義。我見過的例子,其中的關係陣列是連鍵的字典(例如稱爲id
)與參考ID到其他對象的列表,例如:
{"groups":
[{"name": "John's group", "_id": "a",
"members": [
{"_id": "1"},
{"_id": "2"}
]
...
]
}
但我不想改變我的JSON (除此之外,我希望RestKit足夠靈活以支持其他方式)。
有沒有人知道在RestKit中做這種關係映射的正確方法是什麼?
更新
我最後修改REST接口發送包含用戶對象ID(就像上面的最後一個例子)的詞典列表,並得到了工作。仍然不完全滿意的設置,但代碼現在看起來像
RKObjectManager* objectManager = [RKObjectManager sharedManager];
RKManagedObjectMapping* groupMapping = [RKManagedObjectMapping mappingForClass:[Group class] inManagedObjectStore:objectManager.objectStore];
groupMapping.primaryKeyAttribute = @"identifier";
[groupMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping mapKeyPath:@"name" toAttribute:@"name"];
[groupMapping mapKeyPath:@"members._id" toAttribute:@"memberIDs"];
[objectManager.mappingProvider setMapping:groupMapping forKeyPath:@"groups"];
// Create an empty user mapping to handle the relationship mapping
RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class] inManagedObjectStore:objectManager.objectStore];
userMapping.primaryKeyAttribute = @"identifier";
[userMapping mapKeyPath:@"_id" toAttribute:@"identifier"];
[groupMapping hasMany:@"members" withMapping:userMapping];
[groupMapping connectRelationship:@"members" withObjectForPrimaryKeyAttribute:@"memberIDs"];
RKObjectRouter* router = objectManager.router;
[router routeClass:[Group class] toResourcePath:@"/rest/groups/:identifier"];
[router routeClass:[Group class] toResourcePath:@"/rest/groups/" forMethod:RKRequestMethodPOST];
// Assume url is properly defined to point to the right path...
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:url usingBlock:^(RKObjectLoader *loader) {}];
以防萬一這可以幫助其他人在類似的情況。我採取的方法可能仍然存在一些問題,但如此之好(甚至可以處理亂序加載,這很好) - 如果對我的原始問題有答案,仍然樂於聽到任何人的聲音。
嘿!我正在嘗試做同樣的事情,但我想知道,CoreData中的memberIDS類型是什麼?我會盡快嘗試!謝謝! – abisson
@abisson檢查Blake Watters的這個答案:https://groups.google.com/d/msg/restkit/9MG0CPi1aS0/olQGaSiJQjAJ – vitaminwater