从 phone 呼叫切换到应用程序时网络连接丢失
Network connection lost while switching from phone call to app
iOS 应用需要 IVR phone 呼叫才能完成验证。用户接听 phone 电话并接听 returns 应用以继续。这之前工作正常,但是最近开始出现网络连接丢失错误,当用户从 phone 调用切换到应用程序时。我正在使用标准的 NSURLSession 功能进行服务调用。应用程序使用 Soap 服务启动 IVR 呼叫并返回 success/fail 响应。
错误日志:
[connection] nw_read_request_report [C2] Receive failed with error "Software caused
connection abort"
Task <91526D5A-BF88-416A-B035-9441BA6CC550>.<1> HTTP load failed,
1807/0 bytes (error code: -1005 [4:-4]) Task
<91526D5A-BF88-416A-B035-9441BA6CC550>.<1> finished with error [-1005]
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was
lost." UserInfo={_kCFStreamErrorCodeKey=-4,
NSUnderlyingError=0x28086bd80 {Error Domain=kCFErrorDomainCFNetwork
Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData
0x282592670 [0x1ddd28660]>{length = 16, capacity = 16, bytes =
0x100201bbc7676c180000000000000000}, _kCFStreamErrorCodeKey=-4,
_kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <91526D5A-BF88-416A-B035-9441BA6CC550>.<1>,
_NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <91526D5A-BF88-416A-B035-9441BA6CC550>.<1>" ), NSLocalizedDescription=The network connection was lost.,
NSErrorFailingURLStringKey=https://www.url?wsdl,
NSErrorFailingURLKey=https://www.url?wsdl, _kCFStreamErrorDomainKey=4}
The network connection was lost.
在 iOS 13 及更高版本上对此进行了测试。似乎 OS 断开网络连接一段时间,应用程序无法接收网络服务的响应。
这对我有效:
在 AppDelegate 中。
var backgroundUpdateTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0)
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
self.backgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
}
func applicationWillResignActive(_ application: UIApplication) {
self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
}
func applicationDidBecomeActive(_ application: UIApplication) {
self.endBackgroundUpdateTask()
}
这里没有神秘。一旦您切换到另一个应用程序,该应用程序就会退出活动状态(并暂停,即没有 CPU 时间)。此外,一旦应用程序在后台并保留其状态(如果已实现),OS 就没有义务将其保存在内存中并可以随时终止它。
连接(其 OS 部分、套接字等)在挂起时超时或在应用程序终止时断开连接。有一种后台任务方法可以在应用程序变为非活动状态之前完成一些绝对需要完成的事情。唯一的事情是,强烈建议不要将后台任务用于超过 30-60 秒的时间,否则任务会被终止。后台任务有超时时间,但可能会因版本而异。显然,您的案例不太适合后台任务,下载数据可能需要更长的时间并且您无法控制多长时间,您需要诸如“服务”或“守护进程”之类的东西。不确定它们是否存在于 ios.
试着读一下:iOS: Keep an app running like a service
另一件要检查的事情是后台应用程序刷新。它允许应用程序不时唤醒并做一些有用的事情:https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/updating_your_app_with_background_app_refresh?language=objc
iOS 应用需要 IVR phone 呼叫才能完成验证。用户接听 phone 电话并接听 returns 应用以继续。这之前工作正常,但是最近开始出现网络连接丢失错误,当用户从 phone 调用切换到应用程序时。我正在使用标准的 NSURLSession 功能进行服务调用。应用程序使用 Soap 服务启动 IVR 呼叫并返回 success/fail 响应。 错误日志:
[connection] nw_read_request_report [C2] Receive failed with error "Software caused connection abort"
Task <91526D5A-BF88-416A-B035-9441BA6CC550>.<1> HTTP load failed, 1807/0 bytes (error code: -1005 [4:-4]) Task <91526D5A-BF88-416A-B035-9441BA6CC550>.<1> finished with error [-1005] Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x28086bd80 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x282592670 [0x1ddd28660]>{length = 16, capacity = 16, bytes = 0x100201bbc7676c180000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <91526D5A-BF88-416A-B035-9441BA6CC550>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask <91526D5A-BF88-416A-B035-9441BA6CC550>.<1>" ), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://www.url?wsdl, NSErrorFailingURLKey=https://www.url?wsdl, _kCFStreamErrorDomainKey=4} The network connection was lost.
在 iOS 13 及更高版本上对此进行了测试。似乎 OS 断开网络连接一段时间,应用程序无法接收网络服务的响应。
这对我有效: 在 AppDelegate 中。
var backgroundUpdateTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0)
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
self.backgroundUpdateTask = UIBackgroundTaskIdentifier.invalid
}
func applicationWillResignActive(_ application: UIApplication) {
self.backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
self.endBackgroundUpdateTask()
})
}
func applicationDidBecomeActive(_ application: UIApplication) {
self.endBackgroundUpdateTask()
}
这里没有神秘。一旦您切换到另一个应用程序,该应用程序就会退出活动状态(并暂停,即没有 CPU 时间)。此外,一旦应用程序在后台并保留其状态(如果已实现),OS 就没有义务将其保存在内存中并可以随时终止它。
连接(其 OS 部分、套接字等)在挂起时超时或在应用程序终止时断开连接。有一种后台任务方法可以在应用程序变为非活动状态之前完成一些绝对需要完成的事情。唯一的事情是,强烈建议不要将后台任务用于超过 30-60 秒的时间,否则任务会被终止。后台任务有超时时间,但可能会因版本而异。显然,您的案例不太适合后台任务,下载数据可能需要更长的时间并且您无法控制多长时间,您需要诸如“服务”或“守护进程”之类的东西。不确定它们是否存在于 ios.
试着读一下:iOS: Keep an app running like a service
另一件要检查的事情是后台应用程序刷新。它允许应用程序不时唤醒并做一些有用的事情:https://developer.apple.com/documentation/uikit/app_and_environment/scenes/preparing_your_ui_to_run_in_the_background/updating_your_app_with_background_app_refresh?language=objc