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

2023-12-29

我在用NSURLSession用于背景图片上传。根据上传的图像,我的服务器给了我响应,我确实在我的应用程序中进行了相应的更改。但是当我的应用程序在后台上传图像时,我无法获得服务器响应,因为没有完成块。

有没有办法在不使用完成块的情况下获得响应NSURLUploadTask?

这是我的代码:

 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];

但我得到了这个错误..

由于未捕获的异常“NSGenericException”而终止应用程序,原因:“后台会话不支持完成处理程序块。请改为使用代表。

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


有几点想法:

首先,使用以下命令实例化您的会话delegate,因为后台会话必须有一个委托:

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

其次,实例化你的NSURLSessionUploadTask没有完成处理程序,因为添加到后台会话的任务无法使用完成块。另请注意,我使用的是文件 URL 而不是NSData:

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

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

- (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");
    }
}

注意,上面是利用了之前实例化的NSMutableDictionary called responsesData(因为,令我懊恼的是,这些“任务”委托方法是在“会话”级别完成的)。

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

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

显然,让您的应用程序代表做出回应handleEventsForBackgroundURLSession,保存completionHandler,这将在下面的URLSessionDidFinishEventsForBackgroundURLSession method.

- (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当后台会话完成时,在主线程上调用此处理程序:

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

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

正如您所看到的,有一些活动部件,但这基本上就是所需要的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在没有完成块的情况下在 NSURLSession 中获取服务器响应数据 的相关文章

随机推荐

  • 创建 SAML 断言并签署响应

    我有一个 Java Web 应用程序 我想为我的应用程序实现 SAML 单点登录 我有这个GitHub onelogin 程序 https github com onelogin java saml发送请求并获取响应 但它无法正常工作 我在
  • 如何使 IEnumerable 只读?

    为什么是列表list1Instance and p in the Main下面的代码的方法指向同一个集合 class Person public string FirstName string Empty public string Las
  • 将列添加到稀疏矩阵

    当我执行以下代码时 我得到一个稀疏矩阵 import numpy as np from scipy sparse import csr matrix row np array 0 0 1 2 2 2 col np array 0 2 2 0
  • 实体框架是否与 SQL Server 绑定?

    如果我想连接到 Oracle MySQL 甚至 MS Access 怎么办 不 它使用 ADO Net 提供程序 模型插入数据库提供程序以提供对任何第三方数据库的访问 可用列表第三方 EF 提供商在这里 http msdn microsof
  • 进入前台时的 UIRefreshControl 错误

    当我使用时我注意到一个小错误 但真的很烦人 UIRefreshControl在我的视图控制器中 当应用程序从后台返回时UIRefreshControl已经加载 看起来像这样 正如你所看到的 我使用了一个自定义导航控制器 它像 Faceboo
  • 为什么 Google 云端硬盘返回“无法解析内容范围标头。”?

    这是我的简单代码 用于恢复 可能 中断的 Google Drive 上传 Using message New ByteArrayContent New Byte message Headers ContentRange New Header
  • 从左到右表达式求值

    在 C 中 是否保证表达式从左到右计算 例如 myClass GetClass if myClass null myClass Property gt 0 continue 是否存在不符合规定的语言 您实际上指的是一种称为 短路逻辑表达式
  • 如何拥有与 OnPropertyChanged 一起使用的 UserControl 的可绑定属性

    我有一个带有一些公共属性的简单用户控件 WinForms 当我使用此控件时 我想将 DataSourceUpdateMode 设置为的数据绑定到这些属性属性改变时 数据源是一个实现 INotifyPropertyChanged 的 类 我知
  • 如何使用 Django 智能选择来过滤 ManyToManyField?

    class Course models Model course code models CharField max length 100 unique True title models CharField max length 200
  • 插入数据库时​​对密码进行哈希加密

    我正在为学校做一个应用程序 在将密码插入我的用户数据库时需要加密密码的帮助 我正在使用 C 编程语言进行编程 并且使用 MS server 2008 R2 来操作我的数据库 我正在考虑进行哈希加密 如果有人帮助我 我会很高兴 这是我将数据插
  • 查找 System.AccessViolationException 的原因

    我们的应用程序遇到了奇怪的致命 System AccessViolationException 当我们配置 AppDomain CurrentDomain UnhandledException 事件来记录异常时 我们会看到这些 Except
  • 这个 PHP 代码安全吗?

    只是一个简单的问题 以下 PHP 代码安全吗 还有什么你认为我可以或应该补充的吗 post GET post if is numeric post post mysql real escape string post else die NA
  • C# 将一个字符串的一部分复制到另一个字符串

    我正在尝试将文本框的部分文本复制到另一个字符串 例如 如果我的文本框包含 10 个字符 我想将字符 3 到字符 7 复制到另一个名为 TEST 的字符串 我们该怎么做呢 when textbox contains ABCDEFGHIJ th
  • 从 R 中的一系列情节创建电影 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 有没有一种简单的方法可以通过在 R 中将多个情节拼接在一起来创建 电影 这是我使用 R 帮助找到的一种方法 要创建单独的图像帧 jpe
  • 写入 log4net FileAppender 时存在多线程性能问题

    TickZoom 是一款非常高性能的应用程序 它使用自己的并行化库和多个操作系统线程来平滑地利用多核计算机 该应用程序遇到了瓶颈 用户需要从单独的操作系统线程将信息写入 LogAppender FileAppender 使用 Minimal
  • hide() 单选按钮*和*它在 jquery 中的文本标签

    我正在回顾最近的一个项目 解决可访问性问题 并确保所有表单元素都有标签 将标签文本放入标签中会导致我之前编写的一些笨拙代码出现问题 基本上 如果您有一个单选按钮及其标签
  • R 将正数和负数的 $xxx.xx 更改为 xxx.xx 但不舍入

    我有一个 df 其中第 2 列及以后的列是美元金额 例如 1004 23 1482 40 2423 94 等 类似于下面的示例 gt df id desc price 1 0 apple 1 00 2 1 banana 2 25 3 2 g
  • 从 C# 调用时将记录选项返回为 null

    是否有可能返回record option从 F 到 C 的值作为空值 我想将一些逻辑封装在 F 程序集中 并尽可能多地隐藏在外观后面 对 C 来说更自然 这是一些综合示例 type Data DataField1 int DataField
  • 用于信标的 CoreBluetooth

    我有一个需要信标范围的项目 我查看了很多示例代码 它们都使用CLLocationManager and CLBeaconRegion 我的问题是didRangeBeacons每秒仅调用一次回调 尽管我没有找到任何专门针对信标的代码示例 但我
  • 如何在没有完成块的情况下在 NSURLSession 中获取服务器响应数据

    我在用NSURLSession用于背景图片上传 根据上传的图像 我的服务器给了我响应 我确实在我的应用程序中进行了相应的更改 但是当我的应用程序在后台上传图像时 我无法获得服务器响应 因为没有完成块 有没有办法在不使用完成块的情况下获得响应