ios - example - Consultas de fecha de Parse.com y AFNetworking 2.0
afnetworking example (1)
De la documentación de RESE de parse.com aquí :
El valor del parámetro where debe codificarse como JSON. Por lo tanto, si nos fijamos en la URL real solicitada, estaría codificada en JSON, luego codificada en URL
Estás tan cerca de tu cadena codificada, solo necesitas codificar URL para toda la consulta. He tenido éxito con lo siguiente:
NSString *dateQueryString = [NSString stringWithFormat:@"{/"updatedAt/":{/"$gte/":{/"__type/":/"Date/",/"iso/":/"%@/"}}}", dateString];
NSDictionary *parameters = @{@"where": dateQueryString};
A continuación, se usa un NSDictionary para construir la fechaQueryString:
NSString *dateQueryString;
NSDictionary *query = @{ @"updatedAt": @{ @"$gte": @{@"__type":@"Date",@"iso":dateString}}};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:query
options:nil
error:&error];
if (!jsonData) {
NSLog(@"Error: %@", [error localizedDescription]);
}
NSString *dateQueryString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
NSDictionary *parameters = @{@"where": dateQueryString};
Para completar, estoy usando una instancia compartida de una subclase AFHTTPSessionManager:
@implementation ParseAPISessionManager
+ (instancetype)sharedSession {
static ParseAPISessionManager *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[ParseAPISessionManager alloc] initWithBaseURL:[NSURL URLWithString:parseAPIBaseURLString]];
});
return _sharedClient;
}
- (id)initWithBaseURL:(NSURL *)url {
self = [super initWithBaseURL:url];
if (self) {
self.requestSerializer = [AFJSONRequestSerializer serializer];
[self.requestSerializer setValue:parseAPIApplicationId forHTTPHeaderField:@"X-Parse-Application-Id"];
[self.requestSerializer setValue:parseRESTAPIKey forHTTPHeaderField:@"X-Parse-REST-API-Key"];
}
return self;
}
Y llamándolo así:
ParseAPISessionManager *manager = [ParseAPISessionManager sharedSession];
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:13];
[comps setMonth:2];
[comps setYear:2014];
[comps setHour:16];
[comps setMinute:0];
NSDate *feb13 = [[NSCalendar currentCalendar] dateFromComponents:comps];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd''T''HH:mm:ss.''999Z''"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"GMT"]];
NSString *feb13str = [dateFormatter stringFromDate: feb13];
NSString *queryStr = [NSString stringWithFormat:@"{/"updatedAt/":{/"$gte/":{/"__type/":/"Date/",/"iso/":/"%@/"}}}", feb13str];
NSDictionary *parameters = @{@"where": queryStr};
[manager GET:@"classes/TestClass" parameters:parameters success:^(NSURLSessionDataTask *operation, id responseObject) {
NSLog(@"%@", responseObject);
} failure:^(NSURLSessionDataTask *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
Perdón por la publicación larga, espero que ayude
Intento usar AFNetworking 2.0 para obtener registros de un backend de Parse.com. Quiero que los registros se actualicen después de cierta fecha. La documentación de Parse.com indica que las consultas de comparación contra un campo de fecha deben codificarse en url en el formato:
''where={"createdAt":{"$gte":{"__type":"Date","iso":"2011-08-21T18:02:52.249Z"}}}''
Esto funciona perfectamente usando curl.
En mi aplicación, estoy usando AFNetworking 2.0 para ejecutar la consulta de la siguiente manera. Primero configuré el serializador de solicitudes y respuestas al inicializar el cliente compartido:
+ (CSC_ParseClient *)sharedClient {
static CSC_ParseClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSURL *baseURL = [NSURL URLWithString:@"https://api.parse.com"];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
[config setHTTPAdditionalHeaders:@{ @"Accept":@"application/json",
@"Content-type":@"application/json",
@"X-Parse-Application-Id":@"my app ID",
@"X-Parse-REST-API-Key":@"my api key"}];
NSURLCache *cache = [[NSURLCache alloc] initWithMemoryCapacity:10 * 1024 * 1024
diskCapacity:50 * 1024 * 1024
diskPath:nil];
[config setURLCache:cache];
_sharedClient = [[CSC_ParseClient alloc] initWithBaseURL:baseURL
sessionConfiguration:config];
_sharedClient.responseSerializer = [AFJSONResponseSerializer serializer];
_sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
});
return _sharedClient;
}
- (NSURLSessionDataTask *)eventsForSalesMeetingID:(NSString *)meetingID sinceDate:(NSDate *)lastUpdate completion:( void (^)(NSArray *results, NSError *error) )completion {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
[dateFormatter setTimeZone:gmt];
[dateFormatter setDateFormat:@"yyyy-MM-dd''T''HH:mm:ss.SSS''Z''"];
NSString *dateString = [dateFormatter stringFromDate:lastUpdate];
NSLog(@"date = %@", dateString);
NSDictionary *params = @{@"where": @{@"updatedAt": @{@"$gte": @{@"__type":@"Date", @"iso": dateString}}}};
NSURLSessionDataTask *task = [self GET:@"/1/classes/SalesMeetingEvents"
parameters:params
success:^(NSURLSessionDataTask *task, id responseObject) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
NSLog(@"Response = %@", httpResponse);
if (httpResponse.statusCode == 200) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(responseObject[@"results"], nil);
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, nil);
});
NSLog(@"Received: %@", responseObject);
NSLog(@"Received HTTP %d", httpResponse.statusCode);
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
completion(nil, error);
});
}];
return task;
}
Pero esto produce un error 400 del servidor. La cadena de consulta codificada en url devuelta se ve así después de la decodificación:
where[updatedAt][$gte][__type]=Date&where[updatedAt][$gte][iso]=2014-01-07T23:56:29.274Z
Traté de codificar el extremo posterior de la cadena de consulta de esta manera:
NSString *dateQueryString = [NSString stringWithFormat:@"{/"$gte/":{/"__type/":/"Date/",/"iso/":/"%@/"}}", dateString];
NSDictionary *params = @{@"where":@{@"updatedAt":dateQueryString}};
Esto me acerca, pero sigue siendo un error de 400; la cadena de consulta devuelta del servidor se ve así:
where[updatedAt]={"$gte":{"__type":"Date","iso":"2014-01-07T23:56:29.274Z"}}
¿Cómo obtengo la cadena de consulta adecuada de AFNetworking? Comencé usando el ParseSDK, lo que hizo que esta consulta fuera muy fácil, pero su SDK es demasiado pesado (30+ MB).