你不能只返回数据(因为NSURLSessionDataTask
异步运行)。您可能想采用自己的完成块模式,类似于completionHandler
of the dataTaskWithRequest
方法。
因此,您可以将自己的块参数添加到您的方法中,您将从内部调用该块参数dataTaskWithRequest
方法completionHandler
:
+ (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler {
// create your request here ...
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (completionHandler)
completionHandler(data, response, error);
}];
[dataTask resume];
return dataTask;
}
或者,因为这个dataTaskWithRequest
在后台线程上运行,有时确保将完成处理程序分派回主队列很有用,例如
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (completionHandler)
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(data, response, error);
});
}];
请注意,顺便说一句,我认为退回NSURLSessionDataTask
引用,如上,因此 (a) 调用者可以确保数据任务已成功创建; (b) 你有NSURLSessionTask
您可以使用该引用来取消任务,以防在将来的某个日期您希望能够因某种原因取消请求(例如,用户关闭发出请求的视图控制器)。
无论如何,您可以通过以下方式调用它:
NSURLSessionTask *task = [MyClass postCall:parameters fromURL:url completionHandler:^(NSData *data, NSURLResponse *response, 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
}
You ask:
我的方法好还是会给我以后带来麻烦?我没有[an]图像要下载,也没有任何东西要上传,我只需发送[一些]简单的字符串数据并接收[简单]字符串数据。或者在每个函数中独立地编写代码会更好?
如果您收到返回的简单字符串数据,我建议您以 JSON 格式编写响应,然后将完成块放在postCall
use NSJSONSerialization
提取响应。使用 JSON 可以让应用程序更轻松地区分成功响应和可能返回字符串响应的各种与服务器相关的问题。
因此,假设您修改了服务器代码以返回如下响应:
{"response":"some text"}
然后你可以修改postCall
像这样解析该响应:
+ (NSURLSessionDataTask *)postCall:(NSDictionary *)parameters fromURL:(NSString *)url completionHandler:(void (^)(NSString *responseString, NSError *error))completionHandler {
// create your request here ...
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, 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
实例方法(如果需要,可以是单例方法),然后将会话保存为类属性,设置一次,然后在后续查询中重复使用。