2010-12-16 2 views
76

Я новичок в объектно-с, и я начинаю прикладывать большие усилия в отношении запроса/ответа на недавнем уровне. У меня есть рабочий пример, который может вызвать URL-адрес (через http GET) и проанализировать возвращаемый json.Как отправить данные json в запросе Http с использованием NSURLRequest

Рабочий пример этого ниже

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    [responseData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [responseData appendData:data]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 
    NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]); 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
    [connection release]; 
    //do something with the json that comes back ... (the fun part) 
} 

- (void)viewDidLoad 
{ 
    [self searchForStuff:@"iPhone"]; 
} 

-(void)searchForStuff:(NSString *)text 
{ 
    responseData = [[NSMutableData data] retain]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whatever.com/json"]]; 
    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
} 

Мой первый вопрос - будет такой подход масштабов? Или это не async (то есть я блокирую поток пользовательского интерфейса, пока приложение ждет ответа)

Мой второй вопрос: как я могу изменить часть запроса этого, чтобы выполнить POST вместо GET? Это просто изменить HttpMethod так?

[request setHTTPMethod:@"POST"]; 

И, наконец, - как я могу добавить набор данных JSON на этот пост в виде простой строки (например)

{ 
    "magic":{ 
       "real":true 
      }, 
    "options":{ 
       "happy":true, 
       "joy":true, 
       "joy2":true 
       }, 
    "key":"123" 
} 

Спасибо заранее

+1

Вот учебник: HTTP: // mobileorchard .com/tutorial-json-over-http-on-the-iphone/ – Josh 2010-12-16 02:33:04

ответ

101

Вот что я (обратите внимание, что JSON собирается на мой сервер должен быть словарем с одним значением (другой словарь) для ключа = question..ie { : вопрос => {словарь}}):

NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"], 
    [[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"],  nil]; 
NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil]; 
NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"]; 

NSString *jsonRequest = [jsonDict JSONRepresentation]; 

NSLog(@"jsonRequest is %@", jsonRequest); 

NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"]; 

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url 
      cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 


NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding]; 

[request setHTTPMethod:@"POST"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; 
[request setHTTPBody: requestData]; 

NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; 
if (connection) { 
receivedData = [[NSMutableData data] retain]; 
} 

receivedData затем обрабатывается:

NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
NSDictionary *jsonDict = [jsonString JSONValue]; 
NSDictionary *question = [jsonDict objectForKey:@"question"]; 

Это не 100% ясно, и потребуется некоторое повторное чтение , но все должно быть здесь, чтобы вы начали. И из того, что я могу сказать, это асинхронно. Мой пользовательский интерфейс не заблокирован во время этих вызовов. Надеюсь, это поможет.

+0

Все выглядит хорошо, кроме этой строки [dict objectForKey: @ "user_question"], nil]; - dict не указан в вашем примере. Это просто простой словарь или что-то особенное? – 2010-12-19 00:01:23

+1

Извините. Да, «dict» - это просто простой словарь, который я загружаю из документов пользователей iOS. – 2010-12-23 15:55:28

6

Я хотел бы предложить использовать ASIHTTPRequest

ASIHTTPRequest является простым в использовании обертки вокруг CFNetwork API, что делает некоторые из более утомительных аспектов общения с веб-серверами проще. Он написан в Objective-C и работает как в приложениях Mac OS X, так и в iPhone .

Он подходит выполнение основных HTTP запросов и взаимодействия с REST-сервисов (GET/POST/PUT /DELETE). Включенный подкласс ASIFormDataRequest позволяет легко отправлять POST-данные и файлы с использованием multipart/form-data.


Пожалуйста, обратите внимание, что автор прекратил с этим проектом. См. Следующую запись по причинам и альтернативам: http://allseeing-i.com/%5Brequest_release%5D;

Лично я большой поклонник AFNetworking

+0

@ Алмо, вы не читали весь пост, не так ли? – vikingosegundo 2013-07-03 19:01:29

+0

Дух, я этого не делал. Сожалею. – Almo 2013-07-03 19:04:05

2

Вот большая статья с использованием Restkit

Это объясняет на сериализации вложенных данных в формате JSON и приложив данные для запроса HTTP POST.

3

Большинство из вас уже это знают, но я публикую это, просто выставляю, некоторые из вас все еще борются с JSON в iOS6 +.

В iOS6 и более поздних версиях мы имеем NSJSONSerialization Class, который является быстрым и не имеет зависимости от включения «внешних» библиотек.

NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; 

Это путь iOS6 и позже может теперь разобрать использование JSON efficiently.The из SBJson также реализация предварительно ARC и приносит с собой эти вопросы тоже, если вы работаете в среде ARC.

Надеюсь, это поможет!

0

Вот обновленный пример, который использует NSURLConnection + sendAsynchronousRequest: (10.7+, IOS 5 +), Запрос «Сообщение» остается такой же, как с принятым ответ и здесь опущено для ясности:

NSURL *apiURL = [NSURL URLWithString: 
    [NSString stringWithFormat:@"http://www.myserver.com/api/api.php?request=%@", @"someRequest"]]; 
NSURLRequest *request = [NSURLRequest requestWithURL:apiURL]; // this is using GET, for POST examples see the other answers here on this page 
[NSURLConnection sendAsynchronousRequest:request 
            queue:[NSOperationQueue mainQueue] 
         completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 
    if(data.length) { 
     NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
     if(responseString && responseString.length) { 
      NSLog(@"%@", responseString); 
     } 
    } 
}]; 
6

Я боролся с этим некоторое время. Запуск PHP на сервере. Этот код будет опубликовать JSON и получить JSON ответ от сервера

NSURL *url = [NSURL URLWithString:@"http://example.co/index.php"]; 
NSMutableURLRequest *rq = [NSMutableURLRequest requestWithURL:url]; 
[rq setHTTPMethod:@"POST"]; 
NSString *post = [NSString stringWithFormat:@"command1=c1&command2=c2"]; 
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding]; 
[rq setHTTPBody:postData]; 
[rq setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 

[NSURLConnection sendAsynchronousRequest:rq queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) 
{ 
    if ([data length] > 0 && error == nil){ 
     NSError *parseError = nil; 
     NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError]; 
     NSLog(@"Server Response (we want to see a 200 return code) %@",response); 
     NSLog(@"dictionary %@",dictionary); 
    } 
    else if ([data length] == 0 && error == nil){ 
     NSLog(@"no data returned"); 
     //no data, but tried 
    } 
    else if (error != nil) 
    { 
     NSLog(@"there was a download error"); 
     //couldn't download 

    } 
}]; 
2

С моей правкой ответ Mike G, чтобы модернизировать код был отклонен от 3 до 2, как

Это изменение было предназначено для решения автор сообщения и не делает смысл как редактирование. Оно должно быть написано как комментарий или ответ

Я переписываю свое редактирование в качестве отдельного ответа здесь. Это редактирование удаляет зависимость JSONRepresentation с NSJSONSerialization, так как комментарий Роба с 15 подсказками.

NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"], 
     [[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"],  nil]; 
    NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil]; 
    NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

    NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"]; 

    NSLog(@"jsonRequest is %@", jsonRequest); 

    NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"]; 

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url 
       cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 


    NSData *requestData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; //TODO handle error 

    [request setHTTPMethod:@"POST"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
    [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; 
    [request setHTTPBody: requestData]; 

    NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; 
    if (connection) { 
    receivedData = [[NSMutableData data] retain]; 
    } 

receivedData затем обрабатывается:

NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; 
    NSDictionary *question = [jsonDict objectForKey:@"question"]; 
0

Вы можете попробовать этот код для отправки JSON строки

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:ARRAY_CONTAIN_JSON_STRING options:NSJSONWritin*emphasized text*gPrettyPrinted error:NULL]; 
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 
NSString *WS_test = [NSString stringWithFormat:@"www.test.com?xyz.php&param=%@",jsonString];