问题描述
从后台过渡到前台时,我开始发出请求后,我的应用出现了很多网络错误。
错误看起来像这样:
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,NSLocalizedDescription=The network connection was lost.}
该代码是从我的应用的代表触发的:
func applicationWillEnterForeground(_: UIApplication) {
coordinator?.handleWillEnterForeground()
}
从this documentation开始,在此阶段应允许网络请求:
在启动时,系统将您的应用程序以非活动状态启动,然后再将其转换为前台。使用您应用的启动时方法来执行当时所需的任何工作。对于处于后台的应用程序,UIKit可通过调用以下方法之一将您的应用程序移至非活动状态:
此外:
据我所知,inactive
状态意味着您无法与用户进行交互并且事件也没有传递。但是网络请求应该可以正常工作,对吗?知道为什么我的应用程序在不活动时无法运行请求吗?
(我还考虑过使用didBecomeActive
而不是willEnterForeground
,但是在应用启动时也会被调用,所以这并不是我真正需要的。)
编辑:我也碰巧遇到Receive Failed with error "Software caused connection abort"
错误,这些错误与此处讨论的问题(即Xcode的多个版本)无关:Xcode error connecting to simulator "Software caused connection abort"
解决方法
我不知道您所描述的错误的根本原因,但我自己遇到了它。正如您所暗示的,Apple似乎在其自己的系统将其标记为苹果之前就告诉应用程序它们处于前台,因此,被激活后立即发出的请求可能会被阻止(这种情况经常发生,但并非100%时间)。
对我有用的解决方案是只需等待十分之一秒。
您可以通过将通话包装在asyncAfter
通话中来实现
func applicationWillEnterForeground(_: UIApplication) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { [weak self]
self?.coordinator?.handleWillEnterForeground()
}
}
但更可取的是,如果所有请求都通过一个协调器,则让您的AppDelegate代码保持不变,而让协调器查找返回错误代码-1005或53并具有 it 的请求等待十分之一秒,然后重试该请求(确保具有重试限制)。