Câu hỏi Cách gửi dữ liệu json trong yêu cầu Http bằng cách sử dụng NSURLRequest


Tôi mới vào mục tiêu-c và tôi bắt đầu đặt rất nhiều nỗ lực vào yêu cầu / phản hồi như gần đây. Tôi có một ví dụ làm việc có thể gọi một url (thông qua http GET) và phân tích cú pháp json trả về.

Ví dụ làm việc này là dưới đây

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

Câu hỏi đầu tiên của tôi là - cách tiếp cận này sẽ mở rộng quy mô? Hoặc điều này không đồng bộ (nghĩa là tôi chặn luồng giao diện người dùng trong khi ứng dụng đang chờ phản hồi)

Câu hỏi thứ hai của tôi là - làm thế nào tôi có thể sửa đổi một phần yêu cầu của việc này để làm một POST thay vì GET? Chỉ đơn giản là để sửa đổi HttpMethod như vậy?

[request setHTTPMethod:@"POST"];

Và cuối cùng - làm cách nào để thêm một tập hợp dữ liệu json vào bài đăng này dưới dạng một chuỗi đơn giản (ví dụ)

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

Cảm ơn bạn trước


76
2017-12-16 02:30


gốc


Đây là một hướng dẫn: mobileorchard.com/tutorial-json-over-http-on-the-iphone - Josh


Các câu trả lời:


Dưới đây là những gì tôi làm (xin lưu ý rằng JSON đến máy chủ của tôi cần phải là một từ điển với một giá trị (một từ điển khác) cho khóa = question..i.e. {: Question => {dictionary}}):

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

Các receiveData sau đó được xử lý bởi:

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

Đây không phải là 100% rõ ràng và sẽ mất một số đọc lại, nhưng tất cả mọi thứ nên ở đây để giúp bạn bắt đầu. Và từ những gì tôi có thể nói, điều này là không đồng bộ. Giao diện người dùng của tôi không bị khóa trong khi các cuộc gọi này được thực hiện. Hy vọng rằng sẽ giúp.


101
2017-12-17 01:11



Mọi thứ đều tốt ngoại trừ dòng này [dict objectForKey: @ "user_question"], nil]; - dict không được khai báo trong mẫu của bạn. Đây có phải chỉ là một từ điển đơn giản hay một cái gì đó đặc biệt? - Toran Billups
Xin lỗi vì điều đó. Có, "dict" chỉ là một từ điển đơn giản mà tôi tải từ tài liệu người dùng iOS. - Mike G
Điều này đang sử dụng NSDictionary phương pháp thể hiện JSONRepresentation. Tôi có thể đề nghị tôi sử dụng NSJSONSerialization phương pháp lớp dataWithJSONObject, thay cho json-framework. - Rob
Nó là hiệu quả hơn để chuyển đổi NSUInteger thành một NSString thông qua một NSNumber như [[NSNumber numberWithUnsignedInt:requestData.length] stringValue]. - respectTheCode
@MikeG Cố định một lỗi lâu dài và chưa được chú ý trong mẫu mã. Xin lỗi, để chỉnh sửa bài đăng của bạn;) - CouchDeveloper


Tôi sẽ đề nghị sử dụng ASIHTTPRequest

ASIHTTPRequest rất dễ sử dụng   trình bao bọc xung quanh API CFNetwork   làm cho một số khía cạnh tẻ nhạt hơn   giao tiếp với máy chủ web   dễ dàng hơn. Nó được viết trong Objective-C   và hoạt động trên cả Mac OS X và iPhone   các ứng dụng.

Nó là HTTP thực hiện cơ bản phù hợp   yêu cầu và tương tác với   Các dịch vụ dựa trên REST (GET / POST / PUT   / XÓA BỎ). Bao gồm   Lớp con ASIFormDataRequest làm cho nó   dễ dàng gửi dữ liệu và tệp POST   sử dụng multipart / form-data.


Xin lưu ý rằng tác giả gốc đã ngừng sử dụng dự án này. Xem bài đăng theo dõi vì lý do và giải pháp thay thế: http://allseeing-i.com/%5Brequest_release%5D;

Cá nhân tôi là một fan hâm mộ lớn của AFNetworking


6
2017-12-16 02:33



@Almo, bạn đã không đọc toàn bộ bài viết, phải không? - vikingosegundo
Duh, tôi không biết. Lấy làm tiếc. - Almo


Tôi đã vật lộn với điều này một lúc. Chạy PHP trên máy chủ. Mã này sẽ đăng một json và nhận được trả lời json từ máy chủ

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

     }
 }];

6
2018-02-11 15:03



loại nội dung = "ứng dụng / x-www-form-urlencoded" đã làm các trick. Cảm ơn - SamChen
Câu trả lời hay. Tôi đã sử dụng "application / json" trong trường hợp của tôi - Gajendra K Chauhan


Hầu hết các bạn đã biết điều này ngay bây giờ, nhưng tôi đăng bài này, chỉ trong trường hợp, một số bạn vẫn đang đấu tranh với JSON trong iOS6 +.

Trong iOS6 trở lên, chúng tôi có Lớp NSJSONSerialization nhanh và không phụ thuộc vào việc bao gồm thư viện "bên ngoài".

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

Đây là cách iOS6 và sau đó có thể phân tích cú pháp JSON một cách hiệu quả. Việc sử dụng SBJson cũng được thực hiện trước ARC và mang theo những vấn đề đó nếu bạn đang làm việc trong môi trường ARC.

Tôi hi vọng cái này giúp được!


3
2017-11-12 14:49





Đây là một bài viết tuyệt vời sử dụng Restkit

Nó giải thích về việc tuần tự hóa dữ liệu lồng nhau vào JSON và đính kèm dữ liệu vào một yêu cầu HTTP POST.


2
2017-08-19 16:34





Vì câu trả lời của tôi cho câu trả lời của Mike G để hiện đại hóa mã đã bị từ chối từ 3 đến 2

Bản chỉnh sửa này nhằm giải quyết tác giả của bài đăng và không   có ý nghĩa như một bản chỉnh sửa. Nó phải được viết dưới dạng bình luận hoặc   câu trả lời

Tôi đang reposting chỉnh sửa của tôi như là một câu trả lời riêng biệt ở đây. Chỉnh sửa này sẽ xóa JSONRepresentation phụ thuộc với NSJSONSerialization như bình luận của Rob với 15 upvotes cho thấy.

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

Các receiveData sau đó được xử lý bởi:

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

2
2017-11-03 17:54





Dưới đây là ví dụ được cập nhật đang sử dụng NSURLConnection + sendAsynchronousRequest: (10.7+, iOS 5+), Yêu cầu "Đăng" vẫn giữ nguyên như câu trả lời được chấp nhận và bị bỏ qua ở đây vì mục đích rõ ràng:

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

0
2017-12-09 14:42



câu hỏi về POST - ahmad
không, phần đầu tiên của câu hỏi là về asynchronicity và không có câu trả lời ở đây mà câu trả lời đó. Chúc mừng cho downvote. - auco


Bạn có thể thử mã này để gửi chuỗi 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];

0
2017-10-04 12:28