Restkit - 删除具有相同 URL 路径的孤立对象
Posted
技术标签:
【中文标题】Restkit - 删除具有相同 URL 路径的孤立对象【英文标题】:Restkit - Deleting orphaned objects with the same URL path 【发布时间】:2014-08-05 07:13:26 【问题描述】:我已阅读此文档,但它没有显示此问题的任何示例解决方案: 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. District和Building中被删除的对象还在客户端)
- (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 调用时,如何同步这些嵌套实体? 非常感谢!
【问题讨论】:
【参考方案1】:只会使用一个获取请求块。解决您的问题的正确方法是对您的关系使用 Core Data 删除规则,这样删除 Region
会导致 cascade
删除关联的 District
s 和 Building
s。
您在问题中显示的获取请求块会删除上次请求中未收到的所有内容。因为您正在使用 identificationAttributes
和 1:many 关系,所以在删除 Region
之前,接收到的响应可能会将现有的 District
s 和 Building
s 重新连接到新的 Region
,因此级联不会适用于他们。
【讨论】:
【参考方案2】:在我删除那些 addConnectionForRelationship 函数之后。它工作得很好......
【讨论】:
删除addConnectionForRelationship
只是意味着您没有连接关系,它不会从数据存储中删除任何内容。以上是关于Restkit - 删除具有相同 URL 路径的孤立对象的主要内容,如果未能解决你的问题,请参考以下文章