ios – 如何从NSURLSessionDataTask完成处理程序返回NSData

我正在尝试创建一个简单的类,我可以使用它来调用post web服务.

一切都很完美,除了我无法返回NSData.

这是我的代码

+ (NSData *)postCall:(NSDictionary *)parameters fromURL:(Nsstring *)url{
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
    NSMutableArray *pairs = [[NSMutableArray alloc]init];
    for(Nsstring *key in parameters){
        [pairs addobject:[Nsstring stringWithFormat:@"%@=%@",key,parameters[key]]];
    }
    Nsstring *requestParameters = [pairs componentsJoinedByString:@"$"];
    NSURL *nsurl = [NSURL URLWithString:url];
    NSMutableuRLRequest *urlRequest = [NSMutableuRLRequest requestWithURL:nsurl];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:[requestParameters dataUsingEncoding:NSUTF8StringEncoding]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) {
        //return data;
    }];
    [dataTask resume];

    return nil;
}

请注意我有//返回数据,但它给了我这个错误

Incompatible block pointer types sending 'NSData *(^)(NSData *__strong,NSURLResponse *__strong,NSError *__strong)' to parameter of type 'void (^)(NSData *__strong,NSError *__strong)'

我的问题是:

>我的方式好还是将来会给我带来麻烦?我没有要下载的图像,我没有任何要上传内容,我只需要发送简单的字符串数据并接收simpe字符串数据.或者它会更好,但每个函数中的代码是独立的?
>我如何退回数据?

解决方法

您不能只返回数据(因为NSURLSessionDataTask以异步方式运行).您可能希望使用自己的完成块模式,类似于dataTaskWithRequest方法的completionHandler.

因此,您可以将自己的块参数添加到您的方法中,您将从dataTaskWithRequest方法的completionHandler中调用

+ (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(Nsstring *)url completionHandler:(void (^)(NSData *data,NSError *error))completionHandler {

    // create your request here ...

    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data,NSError *error) {
        if (completionHandler)
            completionHandler(data,response,error);
    }];

    [dataTask resume];

    return dataTask;
}

注意,我认为返回NSURLSessionDataTask引用是好的,这样(a)调用者可以确保成功创建数据任务;并且(b)你有NSURLSessionTask参考,你可以用来取消任务,以防万一你希望能够在某个未来的日期取消请求(例如用户解雇请求的视图控制器)发行).

无论如何,你然后用以下方法调用

NSURLSessionTask *task = [MyClass postCall:parameters fromURL:url completionHandler:^(NSData *data,NSError *error) {
    // put whatever code you want to perform when the asynchronous data task completes
}];

if (!task) {
    // handle failure to create task any way you want
}

你问:

Is my way good or it will cause me problems in the future? I don’t have [an] image to download and I don’t have anything to upload,I just have to send [some] simple string data and receive [simple] string data. Or it will be better to but that code in each function independently?

如果您正在接收简单的字符串数据,我建议您以JSON格式编写响应,然后在postCall中使用完成块使用NSJSONSerialization来提取响应.使用JSON可以使应用程序更容易区分成功响应和可能还返回字符串响应的各种服务器相关问题.

所以,假设您修改了服务器代码以返回响应,如下所示:

{"response":"some text"}

然后你可以修改postCall来解析这个响应,如下所示:

+ (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(Nsstring *)url completionHandler:(void (^)(Nsstring *responseString,NSError *error) {
        if (completionHandler) {
            if (error) {
                completionHandler(nil,error);
            } else {
                NSError *parseError = nil;
                NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];

                completionHandler(responseDictionary[@"response"],parseError);
            }
        }
    }];

    [dataTask resume];

    return dataTask;
}

就你的基本问题而言,像postCall这样的方法是否有意义,是的,我认为将创建请求的细节放在单个方法中是完全合理的.我在您的实现中的一个小保留是您决定使其成为类方法而不是实例方法.您当前正在为每个请求创建一个新的NSURLSession.我建议使postCall成为一个实例方法(如果你想要的话是单例),然后将会话保存为类属性,你可以设置一次,然后在后续查询中重复使用.

相关文章

当我们远离最新的 iOS 16 更新版本时,我们听到了困扰 Apple...
欧版/美版 特别说一下,美版选错了 可能会永久丧失4G,不过只...
一般在接外包的时候, 通常第三方需要安装你的app进行测...
前言为了让更多的人永远记住12月13日,各大厂都在这一天将应...