在 iOS 应用程序终止时处理 Alamofire 请求

Posted

技术标签:

【中文标题】在 iOS 应用程序终止时处理 Alamofire 请求【英文标题】:Handling of Alamofire requests as iOS app is terminating 【发布时间】:2017-09-30 17:14:17 【问题描述】:

AppDelegate.applicationWillTerminate 在应用程序即将终止时调用。在这个函数中,我通过 Alamofire 发出一个网络请求,通知服务器应用程序正在终止。 Alamofire 的响应处理程序永远不会被调用。在我看来,终止在调用完成处理程序之前完成。

Alamofire 的完成处理程序似乎在主线程上运行。我发现文档说应用程序负责排空主队列:“虽然您不需要创建主调度队列,但您确实需要确保您的应用程序适当地排空它。有关如何管理此队列的更多信息,请参阅在主线程上执行任务。” (来自https://developer.apple.com/library/content/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html)这就是我卡住的地方。

如何排空主线程?我需要确保最后一个 Alamofire 请求在主线程退出之前运行。

【问题讨论】:

谢谢,我会查看第一个链接。我明白为什么 Alamofire 在闭包中处理响应,这就是它应该这样做的方式。在我看来,ios 在 applicationWillTerminate 返回之前以某种方式(如何?)关闭连接似乎很奇怪。真的是这样吗?相同的请求在其他上下文中运行良好。 【参考方案1】:

不用担心“耗尽”主线程。问题比这更简单。这只是当您的应用离开“前台”/“活动”状态时如何做某事的问题。

当用户离开您的应用去做其他事情时,它通常不会被终止。它进入“暂停”状态,保留在内存中但不执行任何代码。因此,当应用暂停时,它无法处理您的请求(但应用也尚未终止)。

有两种方法可以解决这个问题。

    您可以请求一点时间来完成您的请求(请参阅Extending Your App's Background Execution Time)。通过这样做,您的应用不会暂停,而是暂时进入“后台”状态,在该状态下可以继续执行一小段时间。

    这种方法的优点是过程相当简单。只需在开始请求之前获取后台任务 ID,然后告诉它后台任务已在 Alamofire 完成处理程序中完成。

    这种方法的缺点是您只有 30 秒(以前是 3 分钟)来处理请求。如果您有良好的连接,这通常就足够了。但是,如果您在此期间没有良好的网络连接,则可能永远不会发送请求。

    第二种方法稍微复杂一些:您可以使用背景URLSession 提出请求。在这种情况下,您实际上是在告诉 iOS 接管此请求的处理,并且操作系统将继续这样做,即使您的应用程序暂停(或稍后在其自然生命周期内终止)。

    但这比我概述的第一种方法要复杂得多,并且在此过程中您会失去很多 Alamofire 的易用性和优雅性。您可以扭曲自己来执行此操作(例如,请参阅 https://***.com/a/26542755/1271826),但这与您习惯使用 Alamofire 的明显直观的界面相去甚远。例如,您不能使用简单的response/responseJSON 完成处理程序。您只能下载/上传任务(无数据任务)。您必须编写代码来处理操作系统重新启动您的应用程序以告诉您网络请求已发送(即使您没有对此响应做任何有意义的事情)。等等。

    但是这种更复杂的方法的优点是它更健壮。此过程没有 3 分钟限制。每当重新建立连接时,操作系统仍会代表您发送请求。您的应用甚至可能在该时间点终止,操作系统仍会代表您发送请求。

注意,这些方法都不能处理“强制退出”(例如,用户双击主页按钮并向上滑动以终止应用程序)。它只是处理应用程序正常的优雅离开去做其他事情。

【讨论】:

您说这些解决方案都不适用于“强制退出”。强制退出时有没有办法保证API? 不,没有。

以上是关于在 iOS 应用程序终止时处理 Alamofire 请求的主要内容,如果未能解决你的问题,请参考以下文章

ios、alamofire中的响应处理问题

在 iOS 9 问题上使用 Alamofire 上传带有 URL 参数的图像

从后台获取调用时,Alamofire 不工作

用户终止应用通知 (iOS)

Alamofire 网络错误异常处理

为啥当我在 ios 应用程序中使用 alamofire 时来自服务器的字符串响应会发生变化?