【问题标题】:How to get data to return from NSURLSessionDataTask如何获取数据以从 NSURLSessionDataTask 返回
【发布时间】:2014-01-01 17:57:02
【问题描述】:

我有一个注册视图控制器,它处理所有用户输入并调用另一个类 (wsClass) 中的函数传递给它,该数据作为 NSDictionary。

调用 wsClass 中的函数并建立连接并从服务器返回数据并在会话中可用。

我的问题是如何将该数据返回到最初调用该函数的注册视图控制器,它总是空的。

这是registrationViewController中的调用:

        wsClass *ws = [[wsClass alloc] init];
    NSDictionary *testDict = [[NSDictionary alloc] initWithObjectsAndKeys:username.text,@"username",email.text,@"email",password.text,@"password", nil];
    NSDictionary *respDict = [ws sendData:testDict];

这是 wsClass.m 中调用的函数:

- (NSDictionary *)sendData:(NSDictionary *)sendDict {
NSMutableString *sendStr = [[NSMutableString alloc] init];

[sendDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    [sendStr appendFormat:@"&%@=%@", key, obj];
}];

NSLog(@"sendStr is: %@",sendStr);
NSString *noteDataString = [NSString stringWithFormat:@"%@%@",REQUIRED,sendStr];

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlTest]];
request.HTTPBody = [noteDataString dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPMethod = @"POST";

NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
                                                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                    // The server answers with an error because it doesn't receive the params
                                                    // handle response
                                                    if(error == nil)
                                                    {
                                                        [getReqAlert dismissWithClickedButtonIndex:0 animated:YES];

                                                        NSError *e = nil;
                                                        jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableLeaves error: &e];

                                                        if (!jsonArray) {
                                                            NSLog(@"Error parsing JSON: %@", e);
                                                        } else {

                                                            NSLog(@"resp: %@ = %@",[jsonArray objectForKey:@"status"],[jsonArray objectForKey:@"msg"]);
                                                            NSLog(@"Dictionary count: %lu", jsonArray.count);
                                                        }
                                                    }
                                                }];

 [postDataTask resume];

return jsonArray;

}

【问题讨论】:

    标签: ios objective-c nsurlsession


    【解决方案1】:

    帖子异步完成,因此您的wsClass 需要在帖子完成后告诉调用者完成。一个很好的方法是使用调用者提供的代码块来扩充sendData 方法,该代码块应该在完成时运行:

    sendData: 更改为如下所示:

    // it doesn't return anything, because all it does is launch the post
    // but when the post is done, it invokes completion
    
    - (void)sendData:(NSDictionary *)sendDict completion:(void (^)(NSDictionary *))completion {
    
        // the stuff you're already doing
    
            NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
                completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                // the stuff you're already doing
                // now tell the caller that you're done
                completion(jsonArray);
            }];
        }
    

    调用者现在看起来像这样:

    // change the UI to say "I'm busy doing the post"
    [ws sendData:testDict completion:^(NSDictionary *responseDict) {
        NSLog(@"this runs later, after the post completes %@", responseDict);
        // change the UI to say "The post is done"
    }];
    

    关于此的几点说明:(1) 我没有在块中添加错误参数,您可能应该这样做。检查并使用 nil 和错误,或使用 json 输出和 error=nil 调用块。 (2) 您的代码假定 json 结果解析为字典。在您在代码中假设它之前,请确保它始终是正确的。 (3) 类名通常以大写字母开头。

    【讨论】:

    • 这正是我想要的!谢谢你! ...我将不得不做一些额外的阅读,以充分理解这里完成处理程序的性质。我很好地掌握了这个概念,只是不确定将来使用和参考的语法......再次感谢
    • 乐于助人。作为关于块语法的更一般的答案,这可能会有所帮助:stackoverflow.com/questions/18220645/…。此外,苹果还提供了这份通用指南:developer.apple.com/library/ios/documentation/cocoa/Conceptual/…
    • 在这里创建委托并回拨是否也是一种好习惯?
    • @Woodstock - 是的,从某种意义上说它也可以工作。在我看来,委派被过度使用了,因为块是相对较新的语言添加。我更喜欢委托,只有在委托可以在逻辑上被认为是一个整体类的情况下(当多个类可能充当委托时甚至更好)。
    • @danh 谢谢回复,很有意思!
    【解决方案2】:

    您可以使用信号量等待块完成执行,然后从函数返回值

    - (NSDictionary *)sendData:(NSDictionary *)sendDict {
    NSMutableString *sendStr = [[NSMutableString alloc] init];
    
    [sendDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    [sendStr appendFormat:@"&%@=%@", key, obj];
    }];
    
    NSLog(@"sendStr is: %@",sendStr);
    NSString *noteDataString = [NSString stringWithFormat:@"%@%@",REQUIRED,sendStr];
    
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlTest]];
    request.HTTPBody = [noteDataString dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPMethod = @"POST";
    
    
     let semaphore = dispatch_semaphore_create(0)
    
    NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
    completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // The server answers with an error because it doesn't receive the params
    // handle response
    if(error == nil)
    {
    [getReqAlert dismissWithClickedButtonIndex:0 animated:YES];
    
    NSError *e = nil;
    jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableLeaves error: &e];
    
    if (!jsonArray) {
    NSLog(@"Error parsing JSON: %@", e);
    } else {
    
    NSLog(@"resp: %@ = %@",[jsonArray objectForKey:@"status"],[jsonArray objectForKey:@"msg"]);
    NSLog(@"Dictionary count: %lu", jsonArray.count);
    
         dispatch_semaphore_signal(semaphore)
    }
    }
    }];
    
    [postDataTask resume];
     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    return jsonArray;
    

    }

    【讨论】:

      【解决方案3】:

      这可能有效。

      1. 为 NSDict 或您在类中检索的任何内容添加接口变量 nsDictVariable
      2. 在 SendData 中分配它:self.nsDictVariable = ....

      【讨论】:

        【解决方案4】:

        试试这个。这会很好用。

        -(void)loadDetails
        {
        
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        [[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        
        
            _allVehicleLocationsArray = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        
            [self afterCompleteDoThis];
        
        
        }] resume];
        
        
        }
        
        -(void)afterCompleteDoThis{
        
        for (NSDictionary *vehicleDict in _allVehicleLocationsArray) {
        
            NSLog(@" PPP %@" , [vehicleDict valueForKey:@"vehicleType"]);
        
        }
        }
        

        【讨论】:

          猜你喜欢
          • 2015-01-03
          • 1970-01-01
          • 1970-01-01
          • 2019-06-24
          • 2021-10-20
          • 2018-08-04
          • 1970-01-01
          • 2018-05-16
          相关资源
          最近更新 更多