简体   繁体   English

设备休眠时的 Alamofire 请求

[英]Alamofire requests while device is sleeping

My iOS app receives notification to refresh its state from our main service.我的 iOS 应用程序收到通知以从我们的主要服务刷新其 state。 Right now, we are using Alamofire to fetch the latest state and we play a continues sound when there is updated data.现在,我们正在使用 Alamofire 获取最新的 state,当有更新的数据时,我们会继续播放声音。 Our devices are locked in guided mode to stop them from turning off and provide kiosk experience.我们的设备被锁定在引导模式,以阻止它们关闭并提供信息亭体验。

We are making changes such that the device can go to sleep after xx minutes of inactivity.我们正在进行更改,以便设备在 xx 分钟不活动后可以 go 进入睡眠状态。 However, we ran into a problem where the device was not getting results back from Alamofire even though the request was sent successfully (based on our logs on the api side).但是,我们遇到了一个问题,即即使请求已成功发送,设备也没有从 Alamofire 返回结果(基于我们在 api 端的日志)。

As I am using Alamofire 4, I have setup a singleton with backgroundsessionmanager which is how AF requests are sent now.当我使用 Alamofire 4 时,我已经设置了一个带有backgroundsessionmanager的 singleton,这就是现在发送 AF 请求的方式。 But the challenge is that requests are sent intermittently and fail most of the time when the device is sleeping with this error:但挑战在于,请求是间歇性发送的,并且在设备因以下错误而休眠时大部分时间都会失败:

Domain=NSURLErrorDomain Code=-997 "Lost connection to background transfer service"

Here is my code for singleton (and I have associated code in AppDelegate):这是我的 singleton 代码(我在 AppDelegate 中有相关代码):

class Networking {
    static let sharedInstance = Networking()
    public var sessionManager: Alamofire.SessionManager // most of your web service clients will call through sessionManager
    public var backgroundSessionManager: Alamofire.SessionManager // your web services you intend to keep running when the system backgrounds your app will use this
    private init() {
        self.sessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.default)
        self.backgroundSessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: "com.test.app"))
    }
}

Here is my code for sending the request:这是我发送请求的代码:

let NetworkManager = Networking.sharedInstance.backgroundSessionManager

        
        DispatchQueue.main.async(execute: {
            NetworkManager.request(self.api_url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON{ response in
            
                switch (response.result){
                    case .success:
                        if let jsonResp = response.result.value{
                            print("got the response")
                            print(jsonResp)
                            // parse results
                        }
                    
                    case .failure:
                        print("Network Error: \(response.error)")
                    
                }
            }
        })

I am hoping to get some help to resolve this issue as I am unable to rootcause the inconsistent behavior.我希望得到一些帮助来解决这个问题,因为我无法从根本上导致不一致的行为。 I have read in some places that Apple/iOS will only allow upload/download when the app is in background mode instead of requests .我在某些地方读到 Apple/iOS 仅在应用程序处于后台模式而不是requests时才允许上传/下载。

Yes, background sessions only permit upload and download tasks, not data tasks.是的,后台会话只允许上传和下载任务,不允许数据任务。 They also only permit delegate-based requests, not completion handler-based requests.它们也只允许基于委托的请求,不允许基于完成处理程序的请求。 This answer outlines many of the considerations when doing this in conjunction with Alamofire.这个答案概述了与 Alamofire 一起执行此操作时的许多注意事项。

But this begs the question as to whether you really want to use a background session at all.但这引出了一个问题,即您是否真的想使用背景 session。 When your app is awaken for background fetch, if you're able to finish you request within a reasonable amount of time (eg 30 seconds), you should probably consider a standard session, not a background session.当您的应用程序被唤醒以进行后台获取时,如果您能够在合理的时间内(例如 30 秒)完成您的请求,您可能应该考虑使用标准 session,而不是后台 session。 It's a lot simpler.这要简单得多。

Do not conflate an app running in the “background” with a “background” URLSessionConfiguration : They're completely different patterns.不要将在“后台”中运行的应用程序与“后台” URLSessionConfiguration :它们是完全不同的模式。 Just because your app is running in the background, that doesn't mean you have to use background URLSessionConfiguration .仅仅因为您的应用程序在后台运行,并不意味着您必须使用后台URLSessionConfiguration If your app is running (whether in foreground or in the background), then a standard session is fine.如果您的应用程序正在运行(无论是在前台还是在后台),那么标准的 session 就可以了。 You only need background session if you want it to continue after the app is suspended (or is terminated) and you're willing to encumber yourself with all the extra overhead that background sessions entail.如果您希望它在应用程序暂停(或终止)后继续运行,并且您愿意承担后台会话所需的所有额外开销,则只需要后台 session。

Background sessions are not intended for requests performed while the app is running in the background.后台会话不适用于应用程序在后台运行时执行的请求。 They're intended for requests that will continue after your app is suspended (and even if it eventually is terminated in the course of its natural lifecycle).它们适用于在您的应用程序暂停后将继续的请求(即使它最终在其自然生命周期中终止)。 That means that background sessions are ideal for slow requests that cannot be completed in a reasonable amount of time, eg, downloading video asset, downloading many large image assets or documents, etc.这意味着后台会话非常适合无法在合理时间内完成的缓慢请求,例如下载视频资产、下载许多大型图像资产或文档等。

But if you're just performing a routine GET/POST request that will complete in a reasonable amount of time, consider not using background URLSessionConfiguration , but just do normal request and call the background fetch completion handler when your request is done (ie, in your network request's completion handler).但是,如果您只是执行将在合理的时间内完成的例行 GET/POST 请求,请考虑不使用后台URLSessionConfiguration ,而只是执行正常请求并在您的请求完成时调用后台获取完成处理程序(即,在您的网络请求的完成处理程序)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM