后台下载AlamoFire会话

45

我正在一个新的应用程序中使用Alamofire(基于Alamofire的下载管理器示例),需要对使用后台会话下载文件进行一些澄清。

需要覆盖SessionDelegate才能使其正常工作吗?或者只需要使用backgroundCompletionHandler?

通常,使用Alamofire在后台处理下载的步骤是什么?如何处理应用程序重新启动时仍有下载任务的情况?


1
请访问 https://github.com/Alamofire/Alamofire,转到“下载文件”部分,Alamofire请求是异步的。 - saurabh
3个回答

34

更新

基于这篇精彩的教程,我制作了一个可在GitHub上获取的示例项目。它包含一个后台会话管理的示例。

根据苹果的URL Loading System编程指南

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

因此,通过使用适当的后台会话配置实例,您的下载将永远不会处于“流动”状态。

我还发现这个答案非常有帮助。

原始答案

从Alamofire的GitHub页面

应用程序可以为后台和短暂会话创建管理器,以及自定义默认会话配置的新管理器,例如用于默认标头(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 我明白了。我做了一些研究,请查看更新后的答案,可能会有用。 - József Vesza
非常感谢,虽然不完全符合我的期望,但这绝对是最好的答案。 - LastMove
@JózsefVesza,您能否将您的示例更新至至少Swift 3? - Sneha
如果我使用上述URL发出下载请求,我的destinationURL将为nil,并且使用上述管理器无法下载文件。 @JózsefVesza - Mukul More
显示剩余3条评论

33

编辑

使用 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

在我的情况下,AppDelegate方法如下:

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
    }
}

使用递归函数可以逐个下载多张图片吗? - Monish
这样不行,请参见 https://github.com/Alamofire/Alamofire/commit/1d5411cdde887cb9c8d282239fa4a44d42bd5e9f。 - Tieme
我之前改过我的答案。使用Alamofire 5不再可能了。 - Luca Torella

10

我搜索了很长时间才找到解决方案,直到读到上面提到的文章。对我来说问题在于 - 我必须启用外部附件通信

输入图像描述

其他所有操作都按照上述描述完成。 AppDelegate:

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 ...

1
您的App不需要实际功能来与外部配件通信,以便苹果批准带有此后台模式勾选的应用程序吗? - user2363025
1
为什么需要启用外部配件通信?当提交应用程序到AppStore时,这将成为一个问题。 - bra.Scene
后台同步工作得很好,感谢发布这个答案。 - Iyyappan Ravi
上传到商店时,苹果是否接受此方法? - famfamfam
@famfamfam 不是的。 - Romain Sickenberg
2
当你告诉人们勾选“神奇的框”,却没有解释为什么,或者它如何影响应用商店的接受度时,这是一个非常糟糕的解决方案。 - SafeFastExpressive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接