在 Alamofire 中使用 backgroundCompletionHandler 的正确方法是什么?
What is the correct way to use backgroundCompletionHandler in Alamofire?
我不清楚如何正确使用它,但看到其他人在做这种事情:
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
manager.sharedInstance.backgroundCompletionHandler = completionHandler
}
在我们类似的实现中,此时completionHandler
是partial 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 并且此时消息已经在控制台中可见并且 backgroundCompletionHandler
是 nil
.
我们正在使用 Xcode 7.0 针对 iOS 9 SDK 进行构建,目前使用的是 Alamofire 2.0.2
我最初认为这是在我们合并 Swift 2.0 分支时引入的,但我也看到了使用 Xcode 6.4 针对 iOS 8 SDK 进行的较早提交的消息.
更新 1
解决@cnoon 的建议:
- 标识符匹配 - 配置和管理器设置在单例中,所以不可能出错。
- 在
Manager
backgroundCompletionHandler
class 上的 didSet
内部添加和打印时,消息记录在 之前 警告。
- 当在
Manager
class 内的 delegate
上打印设置为 sessionDidFinishEventsForBackgroundURLSession
的闭包内部时,将在 [=] 之后打印消息95=] 警告。
- 在调用
backgroundCompletionHandler
之前覆盖 sessionDidFinishEventsForBackgroundURLSession
并在其中打印时,消息会在 警告之后打印。
- 至于验证我的 Xcode 项目是否为后台会话正确设置,我不确定如何做,也找不到任何关于如何做的文档。
我应该注意到,在尝试从我的 phone 上传一些屏幕截图时,我最初无法重现此问题以尝试这些建议。
只有在尝试分享一些照片后,我才能再次重现这一点。我不确定或相关性(如果有的话),但这可能与上传时间更长的照片有关。
更新 2
UIBackgroundModes
的设置与@Nick 描述的完全一致,直接在 application:handleEventsForBackgroundURLSession:completionHandler:
内部调用 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
}
据此看来,使用计算的 属性 来代理完成处理程序似乎是问题的原因。
我真的不想公开这个 属性 并且很想知道任何解决方法或替代方案。
看来你所做的一切都是正确的。我有一个示例应用程序,它完全按照您所描述的方式工作,并且不会引发您看到的警告。我猜你在某处仍然有一些小错误。以下是一些可以尝试的想法:
- 验证标识符与后台会话的标识符匹配
- 在
Manager
class 中的 backgroundSessionHandler
上临时添加 didSet
日志语句以验证它是否已设置
- 将日志语句添加到
sessionDidFinishEventsForBackgroundURLSession
以验证它是否按预期被调用
- 覆盖委托上的
sessionDidFinishEventsForBackgroundURLSession
并手动调用 backgroundSessionHandler
- 确认您的 Xcode 项目已为后台会话正确设置
更新 2
您计算的 属性 是错误的。相反,它需要将 backgroundCompletionHandler
设置为 newValue
。否则你永远不会正确地将它设置为新值。请参阅此 thread 了解更多信息。
我不清楚如何正确使用它,但看到其他人在做这种事情:
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
manager.sharedInstance.backgroundCompletionHandler = completionHandler
}
在我们类似的实现中,此时completionHandler
是partial 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 并且此时消息已经在控制台中可见并且 backgroundCompletionHandler
是 nil
.
我们正在使用 Xcode 7.0 针对 iOS 9 SDK 进行构建,目前使用的是 Alamofire 2.0.2
我最初认为这是在我们合并 Swift 2.0 分支时引入的,但我也看到了使用 Xcode 6.4 针对 iOS 8 SDK 进行的较早提交的消息.
更新 1
解决@cnoon 的建议:
- 标识符匹配 - 配置和管理器设置在单例中,所以不可能出错。
- 在
Manager
backgroundCompletionHandler
class 上的didSet
内部添加和打印时,消息记录在 之前 警告。 - 当在
Manager
class 内的delegate
上打印设置为sessionDidFinishEventsForBackgroundURLSession
的闭包内部时,将在 [=] 之后打印消息95=] 警告。 - 在调用
backgroundCompletionHandler
之前覆盖sessionDidFinishEventsForBackgroundURLSession
并在其中打印时,消息会在 警告之后打印。 - 至于验证我的 Xcode 项目是否为后台会话正确设置,我不确定如何做,也找不到任何关于如何做的文档。
我应该注意到,在尝试从我的 phone 上传一些屏幕截图时,我最初无法重现此问题以尝试这些建议。
只有在尝试分享一些照片后,我才能再次重现这一点。我不确定或相关性(如果有的话),但这可能与上传时间更长的照片有关。
更新 2
UIBackgroundModes
的设置与@Nick 描述的完全一致,直接在 application:handleEventsForBackgroundURLSession:completionHandler:
内部调用 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
}
据此看来,使用计算的 属性 来代理完成处理程序似乎是问题的原因。
我真的不想公开这个 属性 并且很想知道任何解决方法或替代方案。
看来你所做的一切都是正确的。我有一个示例应用程序,它完全按照您所描述的方式工作,并且不会引发您看到的警告。我猜你在某处仍然有一些小错误。以下是一些可以尝试的想法:
- 验证标识符与后台会话的标识符匹配
- 在
Manager
class 中的backgroundSessionHandler
上临时添加didSet
日志语句以验证它是否已设置 - 将日志语句添加到
sessionDidFinishEventsForBackgroundURLSession
以验证它是否按预期被调用 - 覆盖委托上的
sessionDidFinishEventsForBackgroundURLSession
并手动调用backgroundSessionHandler
- 确认您的 Xcode 项目已为后台会话正确设置
更新 2
您计算的 属性 是错误的。相反,它需要将 backgroundCompletionHandler
设置为 newValue
。否则你永远不会正确地将它设置为新值。请参阅此 thread 了解更多信息。