当我的应用程序进入前台时运行请求失败,并显示“网络连接已丢失”。

Posted

技术标签:

【中文标题】当我的应用程序进入前台时运行请求失败,并显示“网络连接已丢失”。【英文标题】:Requests run when my app will enter foreground fail with "The network connection was lost." 【发布时间】:2020-08-27 17:11:07 【问题描述】:

在我从后台转换到前台时开始发出请求后,我的应用出现了相当多的网络错误。

错误如下所示:

Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo=NSUnderlyingError=0x2808e85a0 Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo=NSErrorPeerAddressKey=<CFData 0x282550410 [0x1f80cb728]>length = 16, capacity = 16, bytes = 0x10021068c0a8010a0000000000000000, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4, NSErrorFailingURLStringKey=http://192.168.1.10:4200/api/users/sessions, NSErrorFailingURLKey=http://192.168.1.10:4200/api/users/sessions, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.

代码是由我的应用程序的委托触发的:

    func applicationWillEnterForeground(_: UIApplication) 
        coordinator?.handleWillEnterForeground()
    

从this documentation开始,这个阶段应该允许网络请求:

在启动时,系统会以非活动状态启动您的应用,然后再将其转换到前台。使用您应用的启动时方法来执行当时所需的任何工作。对于处于后台的应用,UIKit 通过调用以下方法之一将您的应用移至非活动状态:

对于支持场景的应用 - 相应场景委托对象的 sceneWillEnterForeground(_:) 方法。 对于所有其他应用程序 - applicationWillEnterForeground(_:) 方法。

从后台过渡到前台时,使用这些方法从磁盘加载资源并从网络中获取数据

此外:

如果我进入后台仅 1 秒,网络请求将成功(调用完成处理程序时应用状态将为 active) 如果我等待超过 5 秒,网络请求将出错(当调用完成处理程序时,应用程序状态将为 inactive

据我了解,inactive 状态意味着您无法与用户进行交互,并且事件未传递。但是网络请求应该可以正常工作,对吧?知道为什么我的应用在处于非活动状态时无法运行请求吗?

(我也考虑过使用didBecomeActive 而不是willEnterForeground,但它也会在应用启动时被调用,所以它并不是我真正需要的。)

编辑:我也碰巧遇到了与此处讨论的问题无关的 Receive failed with error "Software caused connection abort" 错误(即 Xcode 的多个版本):Xcode error connecting to simulator "Software caused connection abort"

【问题讨论】:

只是为了澄清我们要解决什么问题:所以你还没有采用场景代理支持? 正确。我没有使用场景代理。 【参考方案1】:

我不知道您所描述的错误的根本原因,但我自己也遇到过。正如您所提到的,苹果似乎在他们自己的系统将它们标记为前台之前告诉应用程序它们处于前台,因此在激活后立即发出的请求可能会被阻止(它经常发生但不是 100%根据我的经验)。

对我有用的解决方案是简单地等待十分之一秒。

您可以通过在asyncAfter 呼叫中包装您的呼叫来做到这一点

func applicationWillEnterForeground(_: UIApplication) 
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1)  [weak self]
        self?.coordinator?.handleWillEnterForeground()
    

但更优选的是,如果您的所有请求都通过单个协调器,请保留您的 AppDelegate 代码相同,而是让协调器查找返回错误代码 -1005 或 53 并具有 it 的请求等待十分之一秒,然后重试请求(确保有重试限制)。

【讨论】:

谢谢。我最终在 URLSession 周围使用了一个包装器,它将根据遇到的错误类型重试请求。 ?

以上是关于当我的应用程序进入前台时运行请求失败,并显示“网络连接已丢失”。的主要内容,如果未能解决你的问题,请参考以下文章

iOS 静默推送通知失败并显示消息

当应用程序进入后台时,URLSessions 给 URLResponse nil

Flutter:当我的应用不在前台时如何显示横幅(如地图/谷歌地图)?

应用程序将进入后台并进入前台遇到黑屏

我的应用程序仅在后台运行 ios 10

当应用程序进入后台时,在前台执行的长时间运行的任务被挂起