gpt4 book ai didi

ios - 如何在没有完成 block 的情况下在 NSURLSession 中获取服务器响应数据

转载 作者:IT王子 更新时间:2023-10-29 07:37:49 27 4
gpt4 key购买 nike

我正在使用 NSURLSession 上传背景图片。根据上传的图片,我的服务器会给我回复,我会相应地更改我的应用程序。但是当我的应用程序在后台上传图片时,我无法获得服务器响应,因为没有完成 block 。

有没有办法在 NSURLUploadTask 中不使用完成 block 来获得响应?

这是我的代码:

 self.uploadTask = [self.session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"returnString : %@",returnString);
NSLog(@"error : %@",error);
}];
[self.uploadTask resume];

但是我得到了这个错误..

Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'

但如果我不能使用完成处理程序,那么我应该如何获得服务器响应。它说使用委托(delegate),但我找不到任何可以给我服务器响应的委托(delegate)方法。

最佳答案

几个想法:

首先,使用委托(delegate)实例化您的 session ,因为后台 session 必须有一个委托(delegate):

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kSessionIdentifier];
self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];

其次,在没有完成处理程序的情况下实例化您的 NSURLSessionUploadTask,因为添加到后台 session 的任务不能使用完成 block 。另请注意,我使用的是文件 URL 而不是 NSData:

NSURLSessionTask *task = [self.session uploadTaskWithRequest:request fromFile:fileURL];
[task resume];

第三,实现相关委托(delegate)方法。至少,这可能看起来像:

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
NSMutableData *responseData = self.responsesData[@(dataTask.taskIdentifier)];
if (!responseData) {
responseData = [NSMutableData dataWithData:data];
self.responsesData[@(dataTask.taskIdentifier)] = responseData;
} else {
[responseData appendData:data];
}
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if (error) {
NSLog(@"%@ failed: %@", task.originalRequest.URL, error);
}

NSMutableData *responseData = self.responsesData[@(task.taskIdentifier)];

if (responseData) {
// my response is JSON; I don't know what yours is, though this handles both

NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
if (response) {
NSLog(@"response = %@", response);
} else {
NSLog(@"responseData = %@", [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]);
}

[self.responsesData removeObjectForKey:@(task.taskIdentifier)];
} else {
NSLog(@"responseData is nil");
}
}

请注意,上面的代码利用了一个名为 responsesData 的先前实例化的 NSMutableDictionary(因为令我懊恼的是,这些“任务”委托(delegate)方法是在“ session ”级别)。

最后,您要确保定义一个属性来存储 handleEventsForBackgroundURLSession 提供的 completionHandler:

@property (nonatomic, copy) void (^backgroundSessionCompletionHandler)(void);

显然,让您的应用委托(delegate)响应 handleEventsForBackgroundURLSession,保存 completionHandler,它将在下面的 URLSessionDidFinishEventsForBackgroundURLSession 方法中使用。

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
// This instantiates the `NSURLSession` and saves the completionHandler.
// I happen to be doing this in my session manager, but you can do this any
// way you want.

[SessionManager sharedManager].backgroundSessionCompletionHandler = completionHandler;
}

然后确保您的 NSURLSessionDelegate 在后台 session 完成时在主线程上调用此处理程序:

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session {
if (self.backgroundSessionCompletionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
self.backgroundSessionCompletionHandler();
self.backgroundSessionCompletionHandler = nil;
});
}
}

仅当某些上传在后台完成时才会调用。

如您所见,其中有几个事件部分,但基本上就是这样。

关于ios - 如何在没有完成 block 的情况下在 NSURLSession 中获取服务器响应数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23731043/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com