菜鸟教程小白 发表于 2022-12-12 18:08:19

ios - NSURLSessionUploadTask 获取响应数据


                                            <p><p>我在使用 <code>NSURLSession</code> 框架时有一些误解,这就是为什么我决定不使用 AFFramework/Alamofire 从头开始​​编写小应用程序。</p>

<p>我有一个 API 需要以下步骤来上传文件:</p>

<ol>
<li>POST 文件数据</li>
<li>获取响应 (JSON)</li>
<li>将一些 json 字段发布到 <code>api/save</code></li>
</ol>

<p>我有这样一个配置的后台 session :</p>

<pre><code>let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(&#34;myBackground&#34;)
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
</code></pre>

<p>我已经实现了两种方法:</p>

<pre><code>func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData)
</code></pre>

<p>我在哪里汇总所有数据</p>

<p>和</p>

<pre><code>func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?)
</code></pre>

<p>我将这些数据转换为响应对象。这个响应对象对我来说非常重要。</p>

<p>一切正常,而应用程序在前台,但我在后台遇到问题。</p>

<p><strong>案例 1</strong></p>

<p>应用程序在我开始上传数据后立即崩溃。根据 WWDC 我需要实现 </p>

<pre><code>func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -&gt; Void)
</code></pre>

<p>并在 <code>didCompleteWithError</code> 方法中调用此处理程序。但在调用此方法之前,我需要使用上传响应中的数据调用 <code>api/save</code> 。
我怎样才能得到这些数据?</p>

<p><strong>案例 2</strong></p>

<p>大部分情况类似。用户在上传过程中停止应用程序。比在几秒钟内加载应用程序,而 session 适用于我的任务。现在 session 调用<code>didReceiveData</code>,当然,有些数据丢失了。在这种情况下我该怎么办?如何恢复响应数据?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>你没有提到实现 <code>URLSessionDidFinishEventsForBackgroundURLSession</code> (一个 <code>NSURLSessionDelegate</code> 方法)。你真的很想实现它。基本流程是:</p>

<ul>
<li><p>在应用代理的 <code>handleEventsForBackgroundURLSession</code> 中,您应该:</p>

<ul>
<li>启动后台<code>NSURLSession</code>(它将开始接收与所有上传相关的委托(delegate)方法调用);和</li>
<li>保存完成处理程序(但不要调用它)。 </li>
</ul></li>
<li><p>然后,在 <code>URLSessionDidFinishEventsForBackgroundURLSession</code> 中(处理完所有响应后),调用保存在 <code>handleEventsForBackgroundURLSession</code> 中的完成处理程序。 (确保将其分派(dispatch)到主队列。)</p></li>
</ul>

<p>如果您正在执行所有这些操作,当后台 session 重新启动时,<code>didReceiveData</code> 调用将与您的各种上传响应一起进入。</p>

<p>我刚刚做了一个快速测试,上传了 5 张 20mb 的图片并立即终止了应用程序。然后,即使应用程序没有运行,我也看到五个文件慢慢出现在我的服务器上(显然由守护进程处理)。当所有五个都完成后,应用程序在后台透明地重新启动,调用 <code>handleEventsForBackgroundURLSession</code> (重新启动 session ),它让所有 <code>didReceiveData</code> 调用快速被调用,完成后,<code>URLSessionDidFinishEventsForBackgroundURLSession</code> 被调用,然后我的应用程序才调用保存的完成处理程序。</p>

<p>就为什么这对您不起作用而言,不足以诊断问题。可能性包括:</p>

<ul>
<li><p>也许你不恰本地终止了应用程序。您不能通过双击主页按钮并在那里终止应用程序来终止应用程序;您必须让它自己自然终止,或者出于诊断/测试目的,我通过在代码中调用 <code>exit(0)</code> 来强制它终止。</p></li>
<li><p>也许你在调用 <code>handleEventsForBackgroundURLSession</code> 时没有重新启动 session 。</p></li>
<li><p>也许您调用提供的完成处理程序太快了(即在调用 <code>URLSessionDidFinishEventsForBackgroundURLSession</code> 之前)。 </p></li>
</ul>

<p>很难说,但我怀疑你的实现中隐藏着一些不太正确的东西,并且根据所提供的信息很难说它是什么(假设它不是上述几点之一)。不幸的是,调试这个后台 session 非常复杂,因为当应用程序终止时,它不再附加到调试器,所以你不能轻易调试应用程序被 iOS 自动重启后发生的事情)。就我个人而言,我要么 <code>NSLog</code> 消息,然后只观察设备控制台(以及观察服务器上显示的内容),要么在应用程序本身中构建一些持久性日志记录机制。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - NSURLSessionUploadTask 获取响应数据,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/34760265/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/34760265/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - NSURLSessionUploadTask 获取响应数据