【问题标题】:Getting data back from an NSURLSession via POST with JSON通过带有 JSON 的 POST 从 NSURLSession 取回数据
【发布时间】:2016-10-04 02:22:52
【问题描述】:

由于 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数据。

【问题讨论】:

  • 您不只是使用 Alamofire 有什么原因吗?它使网络变得非常简单。您是否尝试过上面的代码?它在工作吗?除了希望有人复制/粘贴您的代码并对其进行测试之外,您并没有真正提出真正的问题。至于“这是正确的方法吗?”我会成为一个聪明的亚历克,说不,迁移到 Swift :)
  • 我觉得没问题。你有麻烦吗?在完成处理程序中执行步骤 3 和 4。考虑给这个代码出现的方法一个完成块,以便调用者可以异步获取结果。
  • 我同意 danh。顺便说一句,如果您正在执行多个请求,我还鼓励您不要每次都实例化新的会话对象。实例化会话对象一次。另外,你真的在​​实现委托方法吗?如果没有,我将使用sessionWithConfiguration 进行实例化,而不使用delegatedelegateQueue,或者使用sharedSession。这取决于你。
  • 如果您没有以任何方式修改会话配置并且您没有使用委托,您应该使用共享会话。这就是它的目的。基本上,它就像 NSURLConnection....
  • @danh 和 Rob 如果说我把它放在方法调用中创建块的语法是什么 - (void) getAPI?

标签: ios objective-c json ios9 nsurlsession


【解决方案1】:

让您的方法的调用者提供一个完成处理程序,该处理程序处理返回的数据并更新 UI 以指示完成。

您可以复制SDK中找到的模式,如下:

- (void)makeRequest:(NSString *)param completion:(void (^)(NSDictionary *, NSError *))completion;

这样实现:

// in the same scope
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

- (void)makeRequest:(NSString *)param
         completion:(void (^)(NSDictionary *, NSError *))completion {

    // your OP code goes here, e.g.
    NSError *error;
    NSMutableURLRequest *request = // maybe the param is the url for this request
   // use the already initialized session
    NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request 
        completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

        // call the completion handler 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:@"https://..." 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 {
        // handle the error
    }
}];

注意几点:(1)返回类型是void,调用者不希望从这个方法返回任何东西,调用它时也没有赋值。 “返回”的数据作为参数提供给完成处理程序,稍后在 asnych 请求完成后调用它,(2) 完成处理程序的签名与完成块 ^(NSDictionary *, NSError *) 中声明的调用者完全匹配,这只是一个建议,典型的网络请求。

【讨论】:

    【解决方案2】:
    1. 实例化NSURLSessionNSMutableURLRequest 对象:

      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"];
      
    2. 将您的键值对转换为 JSON:

      // choose the right type for your value.
      NSDictionary *postDict = @{@"key1": value1, @"key2": value2};
      NSData *postData = [NSJSONSerialization dataWithJSONObject:postDict options:0 error:nil];
      
    3. 使用 URL 和 JSON 进行 POST:

      [request setURL:[NSURL URLWithString:@"JSON SERVER"];
      [request setHTTPBody:postData];
      NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
      
      }];
      [postDataTask resume];
      
    4. 解析返回的 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"];
      

    如果您想使用不同的 URL 或 JSON 进行另一个 POST,只需重复步骤 2-4 的流程即可。

    希望我的回答有帮助。

    【讨论】:

    • 解释得很好。谢谢!!
    猜你喜欢
    • 1970-01-01
    • 2013-03-24
    • 2011-03-30
    • 2018-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    相关资源
    最近更新 更多