6

我不清楚如何正确使用它,但见过其他人在做这种事情:

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.

我在这里设置了一个断点,此时消息已经在控制台中可见并且backgroundCompletionHandlernil.

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

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


更新 1

解决@cnoon 的建议:

  • 标识符匹配 - 配置和管理器设置在单例中,因此不可能出错。
  • 在类中添加和打印didSeton时,会在警告之前记录该消息。backgroundCompletionHandlerManager
  • 当在类内部打印闭包sessionDidFinishEventsForBackgroundURLSessiondelegate内部时,在警告之后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
}

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

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

4

1 回答 1

1

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

  • 验证标识符与您的后台会话的标识符匹配
  • 在类中临时添加一条didSet日志语句以验证它是否已设置backgroundSessionHandlerManager
  • 将日志语句添加到中sessionDidFinishEventsForBackgroundURLSession以验证它是否按预期被调用
  • 覆盖sessionDidFinishEventsForBackgroundURLSession委托并手动调用backgroundSessionHandler
  • 验证您是否为后台会话正确设置了 Xcode 项目

更新 2

您的计算属性是错误的。相反,它需要将 设置backgroundCompletionHandlernewValue。否则,您永远不会正确地将其设置为新值。有关更多信息,请参阅此线程

于 2015-09-26T18:47:39.243 回答