Ios 使用JSON通过POST从NSURLSession获取数据

Ios 使用JSON通过POST从NSURLSession获取数据,ios,objective-c,json,ios9,nsurlsession,Ios,Objective C,Json,Ios9,Nsurlsession,由于NSURLConnection已被弃用,我需要转到NSURLSession。我有一个URL和一些数据需要作为JSON输入。那么结果应该是JSON返回。我看到这样的情况: NSError *error; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionW

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

  • 实例化
    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];
    
  • 使用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];
    
  • 在上面的
    completionHandler
    中解析返回的JSON数据:

    if (!error) {                        
        NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
    } else {
        // error code here
    }
    
    responseDict
    是解析的数据。例如,如果服务器返回

    {
        "message":"Your messsage",
        "data1":value1,
        "data2":value2
    }
    
    您可以使用

     [responseDict objectForKey:@"data1"];
    
  • 如果您想用不同的URL或JSON发布另一篇文章,只需重复步骤2-4的流程即可


    希望我的回答有帮助。

    让方法的调用方提供一个完成处理程序,该处理程序处理返回的数据并更新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
        }
    }];
    
    调用此方法的代码如下所示:

    // 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*)
    中声明的完全匹配,这只是一个建议,典型的网络请求。

    您不只是使用Alamofire有什么原因吗?它使网络变得非常简单。你试过上面的代码吗?它起作用了吗?除了希望有人复制/粘贴您的代码并对其进行测试之外,您在这里并没有提出任何真正的问题。至于“这是正确的方法吗?”我会是一个聪明的亚历克,说不,迁移到斯威夫特:)看起来不错。你有问题吗?在completionHandler中执行步骤3和4。考虑给出这个代码出现一个完成块的方法,这样调用方可以异步地得到结果。顺便说一句,如果您正在处理多个请求,我还建议您不要每次都实例化一个新的会话对象。实例化会话对象一次。另外,您真的实现了委托方法吗?如果不是,我只需使用
    sessionWithConfiguration
    实例化,而不使用
    delegate
    delegateQueue
    ,或者使用
    sharedSession
    。这取决于您。如果您没有以任何方式修改会话配置,也没有使用委托,则应使用共享会话。这就是它的目的。基本上,它的行为类似于NSURLConnection…@danh和Rob如果我把它放在方法调用中,创建块的语法是什么?(void)getAPI?解释得很好。非常感谢。