我已阅读此文档但未显示此问题的任何示例解决方案: RKManagedObjectRequestOperation Class Reference
我想使用几个addFetchRequestBlock方法从我正在进行的同一API调用中删除孤立对象。当我删除服务器端的一些记录时,父对象工作正常。但是,Restkit不会删除那些嵌套对象。
我的API JSON输出 - / regions:
(地区有很多地区和建筑物)
(区内有很多建筑物)
{
"regions": [
{
"id": 1,
"name": "region A",
"districts": [
{
"id": 1,
"region_id": 1,
"name": "district A",
"buildings": [
{
"id": 1,
"region_id": 1,
"district_id": 1,
"name": "building A"
},
{
"id": 2,
"region_id": 1,
"district_id": 1,
"name": "building B"
}
]
},
{
"id": 2,
"region_id": 1,
"name": "district B",
"buildings": []
},
{
"id": 3,
"region_id": 1,
"name": "district C",
"buildings": []
}
]
},
{
"id": 2,
"name": "region B",
"districts": [
{
"id": 4,
"region_id": 2,
"name": "district D",
"buildings": [
{
"id": 3,
"region_id": 2,
"district_id": 4,
"name": "building C"
}
]
},
{
"id": 2,
"region_id": 1,
"name": "district E",
"buildings": []
}
]
}
]
}
我的核心数据模型:
我的对象映射和addFetchRequestBlock:
(我试图使用3个addFetchRequestBlock删除孤立对象;调用URL路径时使用Region,District和Building)
(1,Restkit正确删除那些孤立的Region对象)
(2.区和建筑物中已删除的对象仍在客户端)
- (void) setupRegionMappings
{
// Object Mappings
// -------------------------------------------------
// Get RKObjectManager singleton
RKObjectManager *manager = [RKObjectManager sharedManager];
// Get default managed object store
RKManagedObjectStore *managedObjectStore = [RKManagedObjectStore defaultStore];
// Create the RKObjectMapping mapping for our object class:
RKEntityMapping *buildingMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Building class])
inManagedObjectStore:managedObjectStore];
[buildingMapping addAttributeMappingsFromDictionary:@{
@"id": @"buildingID",
@"district_id": @"districtID",
@"region_id": @"regionID",
@"name": @"name",
@"name_zh": @"nameZh",
@"name_cn": @"nameCn",
@"name_en": @"nameEn"
}];
// Identify the object in database
buildingMapping.identificationAttributes = @[@"buildingID"];
// Establish the connection for relation between attributes in core data
[buildingMapping addConnectionForRelationship:@"region" connectedBy:@{@"regionID": @"regionID"}];
[buildingMapping addConnectionForRelationship:@"district" connectedBy:@{@"districtID": @"districtID"}];
[buildingMapping addConnectionForRelationship:@"shops" connectedBy:@{@"buildingID": @"buildingID"}];
// Create the RKObjectMapping mapping for our object class:
RKEntityMapping *districtMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([District class])
inManagedObjectStore:managedObjectStore];
[districtMapping addAttributeMappingsFromDictionary:@{
@"id": @"districtID",
@"region_id": @"regionID",
@"name": @"name",
@"name_zh": @"nameZh",
@"name_cn": @"nameCn",
@"name_en": @"nameEn"
}];
// Identify the object in database
districtMapping.identificationAttributes = @[@"districtID"];
// Establish the connection for relation between attributes in core data
[districtMapping addConnectionForRelationship:@"region" connectedBy:@{@"regionID": @"regionID"}];
[districtMapping addConnectionForRelationship:@"buildings" connectedBy:@{@"districtID": @"districtID"}];
[districtMapping addConnectionForRelationship:@"shops" connectedBy:@{@"districtID": @"districtID"}];
// Define the relationship mapping on json
[districtMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"buildings"
toKeyPath:@"buildings"
withMapping:buildingMapping]];
// Create the RKObjectMapping mapping for our object class:
RKEntityMapping *mapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Region class])
inManagedObjectStore:managedObjectStore];
[mapping addAttributeMappingsFromDictionary:@{
@"id": @"regionID",
@"name": @"name",
@"name_zh": @"nameZh",
@"name_cn": @"nameCn",
@"name_en": @"nameEn"
}];
// Identify the object in database
mapping.identificationAttributes = @[@"regionID"];
// Establish the connection for relation between attributes in core data
[mapping addConnectionForRelationship:@"districts" connectedBy:@{@"regionID": @"regionID"}];
[mapping addConnectionForRelationship:@"buildings" connectedBy:@{@"regionID": @"regionID"}];
[mapping addConnectionForRelationship:@"shops" connectedBy:@{@"regionID": @"regionID"}];
// Define the relationship mapping on json
[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"districts"
toKeyPath:@"districts"
withMapping:districtMapping]];
// The mapping will be triggered if a response status code is anything in 2xx
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
// Put it all together in response descriptor (for a GET request method)
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:@"regions"
keyPath:@"regions"
statusCodes:statusCodes];
// Add response descriptor to our shared manager
[manager addResponseDescriptor:responseDescriptor];
// Routings
// -------------------------------------------------
// Route for list of type objects
RKRoute *indexRoute = [RKRoute routeWithName:@"regions" pathPattern:@"regions" method:RKRequestMethodGET];
indexRoute.shouldEscapePath = YES;
// Add defined routes to the Object Manager router
[manager.router.routeSet addRoutes:@[indexRoute]];
// Making Consistency
// -------------------------------------------------
// Deleting orphaned objects
// Define Fetch request to trigger on specific url
[manager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
// Create a path matcher
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"regions"];
// Dictionary to store request arguments
NSDictionary *argsDict = nil;
// Match the URL with pathMatcher and retrieve arguments
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
// If url matched, create NSFetchRequest
if (match) {
NSFetchRequest *fetchRequest = [Region MR_requestAllSortedBy:@"regionID" ascending:YES];
return fetchRequest;
}
return nil;
}];
[manager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
// Create a path matcher
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"regions"];
// Dictionary to store request arguments
NSDictionary *argsDict = nil;
// Match the URL with pathMatcher and retrieve arguments
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
// If url matched, create NSFetchRequest
if (match) {
NSFetchRequest *fetchRequest = [District MR_requestAllSortedBy:@"districtID" ascending:YES];
return fetchRequest;
}
return nil;
}];
[manager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
// Create a path matcher
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"regions"];
// Dictionary to store request arguments
NSDictionary *argsDict = nil;
// Match the URL with pathMatcher and retrieve arguments
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
// If url matched, create NSFetchRequest
if (match) {
NSFetchRequest *fetchRequest = [Building MR_requestAllSortedBy:@"buildingID" ascending:YES];
return fetchRequest;
}
return nil;
}];
}
当我进行一次相同的API调用时,如何同步这些嵌套实体? 非常感谢!
答案 0 :(得分:1)
将仅使用一个获取请求块。解决问题的正确方法是在关系中使用核心数据删除规则,以便删除Region
会导致cascade
删除关联的District
和{ {1}}秒。
您在问题中显示的抓取请求阻止删除上次请求中未收到的所有内容。由于您使用的是Building
和1:多种关系,因此收到的响应可能会在{{1}之前将现有的identificationAttributes
和District
重新连接到新的Building
删除,因此级联不适用于它们。
答案 1 :(得分:0)
删除那些addConnectionForRelationship函数后。它完美地运作......