如何在iOS背景上与Alamofire保持稳定连接

问题描述 投票:0回答:1

[通过手表,我将命令发送到我的iOS应用。目前尚不清楚原因,但如果应用程序在后台运行,我会看到一些错误:

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

Can't end BackgroundTask: no background task exists with identifier 383 (0x17f), or it may have already been ended. Break in UIApplicationEndBackgroundTaskError() to debug.

我已经尝试将配置更改为后台,并为我的配置使用正确的标识符。我的SessionManager的静态或惰性实现。计数该进程的deinit。

网络会话管理器

static var sessionManager: SessionManager = {
        let configuration = URLSessionConfiguration.background(withIdentifier: UUID().uuidString + ".WatchOS_Background")
        configuration.httpShouldSetCookies = false
        configuration.httpMaximumConnectionsPerHost = 4
        configuration.timeoutIntervalForRequest = 50
        configuration.networkServiceType = .background
        configuration.isDiscretionary = false
        configuration.shouldUseExtendedBackgroundIdleMode = true
        if #available(iOS 13.0, *) {
            configuration.allowsExpensiveNetworkAccess = true
            configuration.allowsConstrainedNetworkAccess = true
        }

        let sessionManager = Alamofire.SessionManager(configuration: configuration)
        sessionManager.delegate.sessionDidBecomeInvalidWithError = { _, error in
            if let error = error {
                print(error)
            }
        }
        sessionManager.delegate.taskDidComplete = { _, task, error in
            if let error = error {
                print(error)
            }
        }
        return sessionManager
    }()

请求示例

func getListFromServer(completion: @escaping (ServiceResponse<[Model1]>) -> Void) {
        let header: HTTPHeaders = ["User-Agent": UserAgentHelper.fullUserAgentString]
        request("/api/1/XXXX", method: .get, parameters: nil, encoding: nil, headers: header).responseData { [weak self] response in
            guard let strongSelf = self else { return }
            completion(strongSelf.completionResponse(response))
        }
    }

请求方法

@discardableResult private func request(
        _ path: String,
        method: HTTPMethod,
        parameters: Parameters? = nil,
        encoding: ParameterEncoding? = nil,
        headers: HTTPHeaders? = nil)
        -> DataRequest {
            let userEncoding = encoding ?? self.defaultEncoding
            let task = beginBackgroundTask()
            let dataRequest = NetworkService.sessionManager.request("\(API)\(path)",
                method: method,
                parameters: parameters,
                encoding: userEncoding,
                headers: headers)

            dataRequest.validate()

            self.endBackgroundTask(taskID: task)
            return dataRequest
    }

开始和结束后台任务

func beginBackgroundTask() -> UIBackgroundTaskIdentifier {
      return UIApplication.shared.beginBackgroundTask(withName: "Background_API", expirationHandler: {})
}

func endBackgroundTask(taskID: UIBackgroundTaskIdentifier) {
      UIApplication.shared.endBackgroundTask(taskID)
}

我希望从您的请求中获得正确的实施,并保持稳定的请求生命周期。

非常感谢您的帮助,对于缺乏技术术语,我们深表歉意。

ios swift alamofire watchkit
1个回答
0
投票

您的核心问题是您没有正确处理后台任务的到期。您必须在任务的到期处理程序中明确结束任务:

let task = UIApplication.shared.beginBackgroundTask(withName: "Background_API") {
    UIApplication.shared.endBackgroundTask(task)
}

[我建议您阅读更多here,其中Apple DTE工程师广泛概述了后台任务处理的要求和极端情况。

此外,Alamofire并不真正支持后台会议。最好将前台会话与后台任务处理结合使用。一旦Alamofire SessionManager被取消初始化,它开始的所有请求都将被取消,即使是在后台会话中也是如此。

最后,在Alamofire响应处理程序中调用validate()无效。您应该在添加响应处理程序之前在请求上调用它,因为它可以在调用处理程序之前验证响应。如果您稍后调用它,它将无法将它产生的错误传递给您的响应处理程序。

© www.soinside.com 2019 - 2024. All rights reserved.