开发者

How to serialize a NSPredicate object?

开发者 https://www.devze.com 2023-01-24 02:35 出处:网络
Is there a way to inspect a NSPredicate object for the purposes of serializing it into a URL? I am trying to retrieve the data remotely and need to translate the predicate object into a URL with query

Is there a way to inspect a NSPredicate object for the purposes of serializing it into a URL? I am trying to retrieve the data remotely and need to translate the predicate object into a URL with querystring parameters that the server understands.

This was inspired by a talk given in WWDC 2010 called "Building a Server Driven User EXperience" where the speakers talk about using Core-Data and with a server backend. I have followed the session video and slides, but am stuck on the serializing point. For example, there is a Person object, and I'm trying to fetch all people whose first name is "John". I am using a subclass of NSManagedObjectContext called R开发者_开发技巧emoteManagedObjectContext, which overrides the executeFetchRequest method, and is supposed to send the call to the server instead. The fetch request is being created as (ellipsed non-essential parts):

@implementation PeopleViewController

- (NSArray *)getPeople {
    RemoteFetchRequest *fetchRequest = [[RemoteFetchRequest alloc] init];
    NSEntityDescription *entity = ...
    NSPredicate *template = [NSPredicate predicateWithFormat:
                                @"name == $NAME AND endpoint = $ENDPOINT"];
    NSPredicate *predicate = [template predicateWithSubstitutionVariables:...];

    [fetchRequest setEntity:entity];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    // the custom subclass of NSManagedObjectContext executes this
    return [remoteMOC executeFetchRequest:fetchRequest error:&error];
}

@end

Now inside the custom subclass of NSManagedObjectContext, how can I serialize the fetch request into querystring parameters suitable for the server. So given the above fetch request, the corresponding URL would be:

http://example.com/people?name=John

It is possible to get a string representation of the predicate which returns,

name == "John" AND endpoint == "people"

that I can parse to get the parameters name, and endpoint. However, is it possible to do it without parsing the string? Here's a partial implementation of the RemoteManagedObjectContext class.

@implementation RemoteManagedObjectContext

- (NSArray *)executeFetchRequest:(NSFetchRequest *)request error:(NSError **)error {
    // this gives name == "John" AND endpoint == "people"
    // don't know how else to retrieve the predicate data
    NSLog(@"%@", [[request predicate] predicateFormat]);

    ...
}

@end


Even better than a string representation is an object-oriented representation! And it's done automatically!

First, check the class of the NSPredicate. It will be an NSCompoundPredicate. Cast it to an appropriate variable.

You'll then see that it's compoundPredicateType is NSAndPredicateType, just like you'd expect.

You can also see that the array returned by -subpredicates reveals 2 NSComparisonPredicates.

The first subpredicate has a left expression of type NSKeyPathExpressionType and a -keyPath of @"name", the operator is NSEqualToPredicateOperatorType. The right expression will be an NSExpression of type NSConstantValueExpressionType, and the -constantValue will be @"John".

The second subpredicate will be similar, except that the left expression's keyPath will be @"endpoint", and the right expression's constantValue will be @"people".

If you want more in-depth information on turning NSPredicates into an HTTP Get request, check out my StackOverflow framework, "StackKit", which does just that. It's basically a framework that behaves similarly to CoreData, but uses StackOverflow.com (or any other stack exchange site) to retrieve information. Underneath, it's doing a lot to convert NSPredicate objects into a URL. You're also welcome to email me any specific questions you have.

0

精彩评论

暂无评论...
验证码 换一张
取 消