【问题标题】:AlamoFire Download in Background Session在后台会话中下载 AlamoFire
【发布时间】:2015-07-20 00:12:13
【问题描述】:

我在一个新应用中使用 Alamofire(基于 Alamofire 的下载管理器示例) 我需要一些关于使用后台会话下载文件的说明。 我需要重写 SessionDelegate 才能让它工作? 还是只是backgroundCompletionHandler

通常使用 Alamofire 在后台处理下载的步骤是什么? 以及如何处理我的应用重新启动、下载量不断变化的情况。

【问题讨论】:

标签: ios swift network-programming alamofire


【解决方案1】:

编辑

对于 Alamofire 5,这不再可能,请参阅发行说明:

不使用带有背景标识符的URLSessionConfiguration 再有可能。我们明确确保 Alamofire 不与 后台会话,以防止围绕支持的持续问题 并让用户感到惊讶。

旧答案,如果您使用 Alamofire 4 仍然有效

使用 Alamofire 其实很简单:

1) 你的 Alamofire.Manager 应该配置一个后台会话标识符:

class NetworkManager {
    ...
    private lazy var backgroundManager: Alamofire.SessionManager = {
        let bundleIdentifier = ...
        return Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: bundleIdentifier + ".background"))
    }()
    ...
}

2) 在 App Delegate 中实现 application(_:handleEventsForBackgroundURLSession:completionHandler: 并将完成处理程序传递给 Alamofire.SessionManager.backgroundCompletionHandler

在我的例子中,应用委托方法看起来像

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    NetworkManager.default.backgroundCompletionHandler = completionHandler
}

我的网络管理器有一个这样的计算属性来设置 Manager 属性:

var backgroundCompletionHandler: (() -> Void)? {
    get {
        return backgroundManager.backgroundCompletionHandler
    }
    set {
        backgroundManager.backgroundCompletionHandler = newValue
    }
}

【讨论】:

【解决方案2】:

我一直在寻找解决方案。直到阅读上面提到的文章。我的问题是 - 我必须启用外部附件通信

其他一切都按上述完成。 应用代理:

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        BackendAPIManager.sharedInstance.backgroundCompletionHandler = completionHandler
    }

单例:

import Alamofire

class BackendAPIManager: NSObject {
    static let sharedInstance = BackendAPIManager()

    var alamoFireManager : Alamofire.SessionManager!

    var backgroundCompletionHandler: (() -> Void)? {
        get {
            return alamoFireManager?.backgroundCompletionHandler
        }
        set {
            alamoFireManager?.backgroundCompletionHandler = newValue
        }
    }

    fileprivate override init()
    {
        let configuration = URLSessionConfiguration.background(withIdentifier: "com.url.background")
        configuration.timeoutIntervalForRequest = 200 // seconds
        configuration.timeoutIntervalForResource = 200
        self.alamoFireManager = Alamofire.SessionManager(configuration: configuration)
    }
}

并且调用是通过以下方式完成的:

BackendAPIManager.sharedInstance.alamoFireManager.upload(multipartFormData: { (multipartFormData) in ...

【讨论】:

  • 您的应用是否不需要实际具有与外部附件通信的功能,以便 Apple 批准选中此后台模式的应用?
  • 为什么需要启用外部附件通信?将应用程序提交到 AppStore 时,这会成为一个问题。
  • 后台同步运行良好,感谢发布此答案。
  • 上传到商店时苹果接受了这个方法吗?
  • 当你告诉人们勾选“魔法框”而不解释原因或它如何影响 App Store 接受度时,这是一个非常糟糕的解决方案。
【解决方案3】:

更新

基于this amazing tutorial,我在GitHub 上整理了一个示例项目。它有一个后台会话管理的示例。

根据苹果的URL Loading System Programming Guide

在 iOS 和 OS X 中,当用户重新启动您的应用时,您的应用 应立即使用 与任何有未完成任务的会话相同的标识符 应用程序最后一次运行,然后为每个创建一个会话 配置对象。这些新会话同样自动 与正在进行的后台活动重新关联。

显然,通过使用适当的后台会话配置实例,您的下载将永远不会“不断变化”。

我还发现this answer 真的很有帮助。

原答案

来自 Alamofire 的GitHub page

应用程序可以为后台和临时创建管理器 会话,以及自定义默认会话的新经理 配置,例如默认标头 (HTTPAdditionalHeaders) 或 超时间隔(timeoutIntervalForRequest)。

默认情况下,顶级方法使用具有默认会话配置的共享 Manager 实例。但是,您可以像这样创建具有后台会话配置的管理器:

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.example.app.background")
let manager = Alamofire.Manager(configuration: configuration)

然后您可以使用此Manager 实例发出请求。

manager.startRequestsImmediately = true
let request = NSURLRequest(URL: NSURL(string: "your.url.here")!)
manager.request(request)

通过查看它的实现,它还有一个名为backgroundCompletionHandler的属性,所以你可以添加一个完成块:

manager.backgroundCompletionHandler = {
        // do something when the request has finished
    }

【讨论】:

  • 感谢您的回复。我已经阅读了 Alamofire 的文档。我的主要问题是“我如何处理我的应用重新启动、下载量不断变化的情况。”
  • @LastMove 我明白了。我做了一些研究,检查更新的答案,它可能有用。
  • 非常感谢,这不是我所期望的,但这是迄今为止最好的答案
  • @LastMove 抱歉,我帮不上忙。我还有一件事要给你:我在this GitHub Repo 有一个示例项目,其中有一个工作后台会话实现。检查“网络”项目。您还可以找到我在描述中使用的资源。根据我的经验,您不必担心应用程序重启,后台会话“自动”工作。希望有帮助! :)
  • FIY startRequestsImmediately 默认为true,谢谢小伙伴的回答
猜你喜欢
  • 2016-03-19
  • 1970-01-01
  • 2016-07-17
  • 2017-03-03
  • 1970-01-01
  • 2014-12-19
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多