在Alamofire中使用backgroundCompletionHandler的正确方法是什么?

时间:2015-09-24 16:40:25

标签: nsurlsession alamofire nsurlsessionconfiguration

我不清楚如何正确使用它,但看到其他人在做这类事情:

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

在我们的类似实施中,此时completionHandlerpartial apply forwarder for reabstraction thunk helper...

其中manager(尽管是单身人士)本质上是:

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

但是,这会导致在控制台中打印以下警告:

Warning: Application delegate received call to -application:handleEventsForBackgroundURLSession:completionHandler: but the completion handler was never called.

我设置了一个断点here,此时该消息已在控制台中显示,backgroundCompletionHandlernil

我们正在使用Xcode 7.0进行iOS 9 SDK构建,目前正在使用Alamofire 2.0.2

我最初认为这是在合并我们的Swift 2.0分支时引入的,但是我也看到了使用Xcode 6.4对iOS 8 SDK进行早期提交的消息。

更新1

解决@ cnoon的建议:

  • 标识符匹配 - 配置和管理器设置在单例内,因此无法出错。
  • didSet课程的backgroundCompletionHandler上的Manager内添加和打印时,会在之前记录警告。
  • sessionDidFinishEventsForBackgroundURLSession课程内的delegate上设置为Manager的封闭内部打印时,会在警告后打印
  • 在调用sessionDidFinishEventsForBackgroundURLSession之前覆盖backgroundCompletionHandler并在其内部打印时,会在>警告后打印消息。
  • 至于验证我是否已为背景会话正确设置了我的Xcode项目,我不知道该怎么做,也找不到任何关于如何操作的文档。

我应该注意,当我尝试从手机上传一些屏幕截图时,我最初无法重现此问题,以便尝试这些建议。

只有在尝试分享一些照片之后我才能再次重现这一点。我不确定或不相关(如果有的话),但可能与上传时间较长的照片有关。

更新2

UIBackgroundModes的设置与@Nick描述的完全相同,直接在completionHandler()内调用application:handleEventsForBackgroundURLSession:completionHandler:不会显示警告。

更新3

所以,我似乎忽略了一个小而重要的细节。 Alamofire.Manager周围的包装器没有直接暴露它。其实施的相关部分如下所示:

private var manager: Manager

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

并在AppDelegate中设置完成处理程序执行该代码路径。

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

我已确认以下更改以公开Alamofire.Manager的实例并直接访问它不会产生警告:

public var manager: Manager

//    public var backgroundCompletionHandler: (() -> Void)? {
//        get {
//            return manager.backgroundCompletionHandler
//        }
//        set {
//            manager.backgroundCompletionHandler = backgroundCompletionHandler
//        }
//    }

AppDelegate

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
    myManager.sharedInstance.manager.backgroundCompletionHandler = completionHandler
}

基于此,似乎使用计算属性代理完成处理程序是问题的原因。

我真的不想公开这个属性,并且想知道任何变通方法或替代方案。

1 个答案:

答案 0 :(得分:1)

看起来你正在做的一切都是正确的。我有一个示例应用程序,它完全按照您所描述的正常工作,并且不会抛出您看到的警告。我猜你在某处仍然有一些小错误。以下是一些尝试的想法:

  • 验证标识符是否与后台会话的标识符匹配
  • 暂时在didSet课程的backgroundSessionHandler上添加Manager日志声明以验证其是否已设置
  • sessionDidFinishEventsForBackgroundURLSession中添加一条日志语句,以验证它是否按预期调用
  • 覆盖委托上的sessionDidFinishEventsForBackgroundURLSession并手动调用backgroundSessionHandler
  • 确认您的Xcode项目已正确设置为后台会话

更新2

您的计算属性错误。相反,它需要将backgroundCompletionHandler设置为newValue。否则,您永远不会正确地将其设置为新值。有关详细信息,请参阅此thread