Can't get RKPathMatcher *pathMatcher to match

2019-07-29 03:16发布

问题:

I have the following mappings:

RKResponseDescriptor *productionParametersPerEquipment = [RKResponseDescriptor responseDescriptorWithMapping:productionParameterMapping
                                                                                                 pathPattern:@"/api/rest/productionparameters/?equipment=:equipment_id"
                                                                                                     keyPath:@"objects"
                                                                                                 statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

and then I have:

[objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
    RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/rest/productionparameters/?equipment=:equipment_id"];

    NSDictionary *argsDict = nil;
    BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
    NSString *productionParameterID;
    if (match) {
        productionParameterID = [argsDict objectForKey:@"id"];
        NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ProductionParameter"];
        fetchRequest.predicate = [NSPredicate predicateWithFormat:@"identifier = %@", @([productionParameterID integerValue])]; // NOTE: Coerced from string to number
        fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES] ];
        return fetchRequest;
    }

    return nil;
}];

However, whenever I call the following, it never matches, hence my orphans are never deleted. Any ideas?

[[RKObjectManager sharedManager] getObjectsAtPath:[NSString stringWithFormat:@"/api/rest/productionparameters/?equipment=%@",_equipment.identifier] parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)

回答1:

The pattern matcher can not match against patterns in the query string of the URL. Anything in the query needs to be handled separately. You should pattern match against the URL path and then query and process the parameters if / when the pattern matches.

Note, this pattern matching limitation applies outside of the scope of the deletion processing too.

So, set your pattern to match to /api/rest/productionparameters. Once you get a match you want to get the query from the URL. You can then use componentsSeparatedByString: to split the query parameters into key value pairs and then process each pair till you find equipment and extract the id.

Incidentally, the pattern would never have returned you [argsDict objectForKey:@"id"] anyway because you set the pattern parameter to equipment_id.


Typed on iPad so check, you probably want to add some checks on array counts too...:

[objectManager addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
    RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/api/rest/productionparameters"];

    NSDictionary *argsDict = nil;
    BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
    NSString *productionParameterID;

    if (match) {

        NSArray queryItems = [[URL query] componentsSeparatedByString:@"&"];

        for (NSString *item in queryItems) {

             NSArray *keyValPair = [item componentsSeparatedByString:@"="];

             if ([keyValPair[0] isEqualToString:@"equipment"]) {
                 productionParameterID = keyValPair[1];
                 NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"ProductionParameter"];
                 fetchRequest.predicate = [NSPredicate predicateWithFormat:@"identifier = %@", @([productionParameterID integerValue])]; // NOTE: Coerced from string to number
                 fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"order" ascending:YES] ];

                return fetchRequest;
            }
        }
    }

    return nil;
}];


回答2:

Use [URL relativeString] instead of [URL relativePath], as relativePath omits the query string.

RKPathMatcher matchesPath: with tokenizeQueryStrings:YES will insert the parameters into the passed dictionary.