Restkit - 删除具有相同URL路径的孤立对象

时间:2014-08-05 07:13:26

标签: ios objective-c restkit restkit-0.20

我已阅读此文档但未显示此问题的任何示例解决方案: 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": []
            }
        ]
    }
]
}

我的核心数据模型:

enter image description here


我的对象映射和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调用时,如何同步这些嵌套实体? 非常感谢!

2 个答案:

答案 0 :(得分:1)

将仅使用一个获取请求块。解决问题的正确方法是在关系中使用核心数据删除规则,以便删除Region会导致cascade删除关联的District和{ {1}}秒。

您在问题中显示的抓取请求阻止删除上次请求中未收到的所有内容。由于您使用的是Building和1:多种关系,因此收到的响应可能会在{{1}之前将现有的identificationAttributesDistrict重新连接到新的Building删除,因此级联不适用于它们。

答案 1 :(得分:0)

删除那些addConnectionForRelationship函数后。它完美地运作......