How to serialize a NSPredicate object?
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.
精彩评论