2014-01-08 49 views
4

我試圖使用AFNetworking 2.0從Parse.com後端獲取記錄。我想在某個日期後更新記錄。 Parse.com文件指出,對日期字段比較查詢需要進行網址的格式編碼:Parse.com和AFNetworking 2.0日期查詢

'where={"createdAt":{"$gte":{"__type":"Date","iso":"2011-08-21T18:02:52.249Z"}}}' 

這工作完全使用curl。

在我的應用程序中,我使用AFNetworking 2.0運行查詢如下。我首先初始化共享客戶端時所設置的請求和響應串行:

+ (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; 

}

但是這會產生從服務器400的錯誤。該URL編碼的查詢字符串解碼後返回這個樣子的:

where[updatedAt][$gte][__type]=Date&where[updatedAt][$gte][iso]=2014-01-07T23:56:29.274Z 

我試圖硬編碼的查詢字符串這樣的後端:

NSString *dateQueryString = [NSString stringWithFormat:@"{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%@\"}}", dateString]; 


NSDictionary *params = @{@"where":@{@"updatedAt":dateQueryString}}; 

這讓我更接近,但仍然是一個400錯誤;從服務器返回的查詢字符串如下所示:

where[updatedAt]={"$gte":{"__type":"Date","iso":"2014-01-07T23:56:29.274Z"}} 

如何從AFNetworking獲取正確的查詢字符串?我開始使用ParseSDK,這使得這個查詢變得非常簡單,但是他們的SDK是沉重的(30+ MB)。

+1

是您的'requestSerializer'設置爲'AFJSONRequestSerializer'的實例? –

+0

看起來它仍然被設置爲默認的「AFHTTPRequestSerializer」。 –

+0

不,共享客戶端設置爲使用JSON序列化程序: – Alpinista

回答

2

從parse.com REST文檔here

的值,其中參數應被編碼JSON。因此,如果你看看請求的實際URL,這將是JSON編碼,然後URL編碼

你是如此接近你的硬編碼字符串,你只需要URL編碼整個查詢。我曾與以下成功:

NSString *dateQueryString = [NSString stringWithFormat:@"{\"updatedAt\":{\"$gte\":{\"__type\":\"Date\",\"iso\":\"%@\"}}}", dateString]; 
NSDictionary *parameters = @{@"where": dateQueryString}; 

下面以一個NSDictionary構建dateQueryString:

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}; 

爲了完整性 - 我使用的是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; 
} 

並且像這樣調用它:

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); 
}]; 

對不起,長的帖子,希望它有助於

+0

感謝Piskin;我放棄了希望得到答案...然而,與此同時,我將整個項目移到了StackMob,我可以使用Core Data方法並NSPredicates查詢我的後端。 – Alpinista

+0

不用擔心@Alpinista,關於StackMob的警告 - 他們在12月被Paypal收購,並在5月份關閉! https://blog.stackmob.com/2014/02/stackmob-announcement/爲了這個原因,我不得不從stackMob進行解析。 – Pliskin