Возвращение данных из NSURLSession через POST с JSON
Поскольку NSURLConnection больше не поддерживается, мне нужно перейти к NSURLSession. У меня есть URL и некоторые данные, которые мне нужно ввести как JSON. Тогда результатом должно быть возвращение JSON. Я вижу что-то вроде этого:
NSError *error;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:@"[JSON SERVER"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPMethod:@"POST"];
NSDictionary *mapData = [[NSDictionary alloc] initWithObjectsAndKeys: @"TEST IOS", @"name",
@"IOS TYPE", @"typemap",
nil];
NSData *postData = [NSJSONSerialization dataWithJSONObject:mapData options:0 error:&error];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
[postDataTask resume];
Я это правильный подход?
Мои требования: 1. Преврати мои пары ключ-значение в JSON. 2. Передайте URL и JSON в функцию многократного использования. 3. Получить возвращенные данные JSON. 4. Разобрать возвращенные данные JSON.
2 ответа
Вы хотите, чтобы вызывающие в вашем методе предоставили обработчик завершения, который выполняет такие вещи, как обработка возвращаемых данных или обновление пользовательского интерфейса, чтобы указать завершение.
Как и в SDK, вы можете сделать то же самое, как описано ниже. Скажем, мы называем функцию makeRequest
и требуется параметр, чтобы отправить как часть запроса. Объявите метод следующим образом:
- (void)makeRequest:(NSString *)param completion:(void (^)(NSDictionary *, NSError *))completion;
Реализуйте это так:
- (void)makeRequest:(NSString *)param
completion:(void (^)(NSDictionary *, NSError *))completion {
// your OP code goes here, e.g.
NSError *error;
NSURLSessionConfiguration *configuration = // and so on
// use the param to form the request if it needs one, then...
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// here, we must abide by the interface of our completion handler.
// we must call in EVERY code path, so the caller is never left waiting
if (!error) {
// convert the NSData response to a dictionary
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error) {
// there was a parse error...maybe log it here, too
completion(nil, error);
} else {
// success!
completion(dictionary, nil);
}
} else {
// error from the session...maybe log it here, too
completion(nil, error);
}
}];
[postDataTask resume];
}
Ваш код, который вызывает этот метод, будет выглядеть так:
// update the UI here to say "I'm busy making a request"
// call your function, which you've given a completion handler
[self makeRequest:@"someParam" completion:^(NSDictionary *someResult, NSError *error) {
// here, update the UI to say "Not busy anymore"
if (!error) {
// update the model, which should cause views that depend on the model to update
// e.g. [self.someUITableView reloadData];
} else {
// update UI to indicate error or take remedial action
}
}];
Обратите внимание на пару вещей: (1) тип возвращаемого значения void
вызывающая сторона не ожидает ничего от этого метода и не присваивает его при вызове. "Возвращенные" данные предоставляются в качестве параметров обработчику завершения, который вызывается позже, после того, как запрос asnych завершен, (2) подпись обработчика завершения точно соответствует тому, что вызывающая сторона объявила в блоке завершения ^(NSDictionary *, NSError *)
Это всего лишь предложение, типичное для сетевых запросов.
Создать экземпляр
NSURLSession
а такжеNSMutableURLRequest
объект:NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
Превратите ваши пары ключ-значение в JSON:
// choose the right type for your value. NSDictionary *postDict = @{@"key1": value1, @"key2": value2}; NSData *postData = [NSJSONSerialization dataWithJSONObject:postDict options:0 error:nil];
Создайте свой POST с помощью URL и JSON:
[request setURL:[NSURL URLWithString:@"JSON SERVER"]; [request setHTTPBody:postData]; NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { }]; [postDataTask resume];
Разобрать данные JSON, возвращенные в
completionHandler
выше:if (!error) { NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; } else { // error code here }
responseDict
это проанализированные данные. Например, если сервер возвращает{ "message":"Your messsage", "data1":value1, "data2":value2 }
Вы можете легко получить значение для
data1
используя[responseDict objectForKey:@"data1"];
Если вы хотите сделать еще один POST с другим URL или JSON, просто повторите последовательность шагов 2-4.
Надеюсь, мой ответ поможет.