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

Dir*_*nry 7 ios appdelegate swift

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

\n

错误看起来像这样:

\n
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.}\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n
    func applicationWillEnterForeground(_: UIApplication) {\n        coordinator?.handleWillEnterForeground()\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

本文档来看,现阶段应允许网络请求:

\n
\n

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

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

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

\n
\n

而且:

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

根据我的理解,inactive状态意味着您无法与用户交互并且事件不会被传递。但是网络请求应该可以正常工作,对吗?知道为什么我的应用程序在不活动时无法运行请求吗?

\n

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

\n

编辑:我也碰巧遇到了Receive failed with error "Software caused connection abort"与此处讨论的问题无关的错误(即 Xcode 的多个版本):Xcode 错误连接到模拟器“软件导致连接中止”

\n

Jam*_*e A 6

我不知道你所描述的错误的根本原因,但我自己也遇到过。正如您所提到的,Apple 似乎在应用程序自己的系统将其标记为前台之前就告诉应用程序它们位于前台,因此在变为活动状态后立即发出的请求可能会被阻止(这种情况经常发生,但不是 100%)以我的经验来看)。

对我有用的解决方案是只需等待十分之一秒。

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

func applicationWillEnterForeground(_: UIApplication) {
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { [weak self]
        self?.coordinator?.handleWillEnterForeground()
    }
}
Run Code Online (Sandbox Code Playgroud)

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