如何将后台任务标识符传递给完成处理程序?
How to pass background task identifier to completion handler?
我看到很多使用 class 成员变量将后台任务的值传递给完成块的示例:
self.bgTask = UIApplication.sharedApplication()
.beginBackgroundTaskWithName("bg task", expirationHandler: { () -> Void in
UIApplication.sharedApplication().endBackgroundTask(self.bgTask)
self.bgTask = UIBackgroundTaskInvalid
})
如果此代码被调用两次,第二次是在第一个后台任务仍然是 运行 时,那么 self.bgTask
将被新任务的标识符覆盖,并且 UIApplication.sharedApplication().endBackgroundTask(self.bgTask)
可能永远不会接到电话。
如果我声明一个局部变量,那么它的值在初始化之前被闭包捕获。也不行。
如何安全地将任务 ID 传递给它的完成处理程序?如果我上面的推理有误,请指正。
在 ObjC 中,您通常会使用 __block
变量来执行此操作,例如:
__block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Expired: %lu", (unsigned long)bgTask);
}];
NSLog(@"Background: %lu", (unsigned long)bgTask);
这会捕获 bgTask
作为块的可变变量。当块被复制时,它被移动到堆中,局部变量 bgTask
成为指向它的间接指针。请参阅 Blocks Tips & Tricks.
中 bbum 更详尽的解释
如果您想将其分配给 属性,没问题,但您不需要。
Swift 没有 __block
属性,但它在没有任何帮助的情况下做了正确的事情。您只需要给它一个 var
即可使用。
func goBackground() {
let app = UIApplication.sharedApplication()
var bgTask: UIBackgroundTaskIdentifier = 0
bgTask = app.beginBackgroundTaskWithExpirationHandler({
NSLog("Expired: %lu", bgTask)
app.endBackgroundTask(bgTask)
})
NSLog("Background: %lu", bgTask)
}
func applicationDidEnterBackground(application: UIApplication) {
goBackground()
goBackground()
}
同样,没有必要将值存储在 属性 中,除非您出于其他原因需要它。该值作为局部变量存储在闭包内。
这是了解闭包的重要内容,也是 Swift 的一个非常强大的功能。这与让您执行此操作相同:
var n = 0
let nextNat = { n++ }
println(nextNat()) // => 0
println(nextNat()) // => 1
您必须结束上一个任务并开始一个新任务
`
var uiBackgroundTaskIdentifier: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0)
func beingOrEndBackgroundUpdateTask() {
DispatchQueue.main.async { [self] in
switch UIApplication.shared.applicationState {
case .background, .inactive:
beginBackgroundUpdateTask()
case .active:
endBackgroundUpdateTask()
default:
break
}
}
}
func beginBackgroundUpdateTask() {
// end previous task
endBackgroundUpdateTask()
self.uiBackgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks") {
// End the task if time expires.
self.endBackgroundUpdateTask()
}
}
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.uiBackgroundTaskIdentifier)
self.uiBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid
}
`
我看到很多使用 class 成员变量将后台任务的值传递给完成块的示例:
self.bgTask = UIApplication.sharedApplication()
.beginBackgroundTaskWithName("bg task", expirationHandler: { () -> Void in
UIApplication.sharedApplication().endBackgroundTask(self.bgTask)
self.bgTask = UIBackgroundTaskInvalid
})
如果此代码被调用两次,第二次是在第一个后台任务仍然是 运行 时,那么 self.bgTask
将被新任务的标识符覆盖,并且 UIApplication.sharedApplication().endBackgroundTask(self.bgTask)
可能永远不会接到电话。
如果我声明一个局部变量,那么它的值在初始化之前被闭包捕获。也不行。
如何安全地将任务 ID 传递给它的完成处理程序?如果我上面的推理有误,请指正。
在 ObjC 中,您通常会使用 __block
变量来执行此操作,例如:
__block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(@"Expired: %lu", (unsigned long)bgTask);
}];
NSLog(@"Background: %lu", (unsigned long)bgTask);
这会捕获 bgTask
作为块的可变变量。当块被复制时,它被移动到堆中,局部变量 bgTask
成为指向它的间接指针。请参阅 Blocks Tips & Tricks.
如果您想将其分配给 属性,没问题,但您不需要。
Swift 没有 __block
属性,但它在没有任何帮助的情况下做了正确的事情。您只需要给它一个 var
即可使用。
func goBackground() {
let app = UIApplication.sharedApplication()
var bgTask: UIBackgroundTaskIdentifier = 0
bgTask = app.beginBackgroundTaskWithExpirationHandler({
NSLog("Expired: %lu", bgTask)
app.endBackgroundTask(bgTask)
})
NSLog("Background: %lu", bgTask)
}
func applicationDidEnterBackground(application: UIApplication) {
goBackground()
goBackground()
}
同样,没有必要将值存储在 属性 中,除非您出于其他原因需要它。该值作为局部变量存储在闭包内。
这是了解闭包的重要内容,也是 Swift 的一个非常强大的功能。这与让您执行此操作相同:
var n = 0
let nextNat = { n++ }
println(nextNat()) // => 0
println(nextNat()) // => 1
您必须结束上一个任务并开始一个新任务 `
var uiBackgroundTaskIdentifier: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier(rawValue: 0)
func beingOrEndBackgroundUpdateTask() {
DispatchQueue.main.async { [self] in
switch UIApplication.shared.applicationState {
case .background, .inactive:
beginBackgroundUpdateTask()
case .active:
endBackgroundUpdateTask()
default:
break
}
}
}
func beginBackgroundUpdateTask() {
// end previous task
endBackgroundUpdateTask()
self.uiBackgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask (withName: "Finish Network Tasks") {
// End the task if time expires.
self.endBackgroundUpdateTask()
}
}
func endBackgroundUpdateTask() {
UIApplication.shared.endBackgroundTask(self.uiBackgroundTaskIdentifier)
self.uiBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid
}
`