在 DispatchGroup 完成之前关闭 vc 会使应用程序崩溃吗?
Will dismissing a vc before a DispatchGroup finishes crash the app?
我知道您必须平衡 DispatchGroup
对 .enter()
和 .leave()
的调用。
问题是,如果我在调用平衡之前启动 dispatchGroup.enter()
和 dismissed/popped
vc,应用程序会崩溃吗?基本上,deinit()
会因为 vc 不在内存中而改变结果吗?
例如。这开始了,但在第 3 个后台任务完成之前,vc 被关闭或弹出。 .leave()
只 运行 两次,但应该 运行 3 次。这只是一个简单的例子来理解这个想法:
func viewDidLoad()
let group = DispatchGroup()
// there are 3 background tasks
for task in backgroundTasks {
group.enter()
someBackgroundTask(... completion: { (_) in
group.leave()
})
}
group.notify...
}
不,调用 leave
失败本身不会导致崩溃。 (这里可能不相关,但调用 leave
太多次会崩溃。)
不过,在所有 enter
调用都被 leave
调用抵消之前,调度组不会被释放。更糟糕的是,完成处理程序和 notify
闭包强烈捕获的任何内容都不会被释放。因此,您确实希望确保所有 enter
调用最终都被 leave
调用所抵消。
但我首先建议确认 leave
没有被调用足够的次数。通常会出现完全相反的问题,leave
被调用了正确的次数,但是这些后台任务中的一个或多个在视图控制器被关闭后完成,并且确实不能优雅地处理这种情况。
对于它的价值,如果 someBackgroundTask
正在做一些在视图控制器被关闭后不再需要的事情,我们会:
尽可能将 someBackgroundTask
设为可取消的任务;
确保各种闭包不维护对视图控制器的强引用(通过使用[weak self]
模式),消除强引用循环;
如果视图控制器在闭包运行时被释放,请确保闭包能够正常处理,例如
group.notify(queue: .main) { [weak self] in
guard let self = self else { return }
...
}
和
在视图控制器的 deinit
中(或等效的地方)取消不再需要的任务(同样,假设它是一个可取消的任务)。
我知道您必须平衡 DispatchGroup
对 .enter()
和 .leave()
的调用。
问题是,如果我在调用平衡之前启动 dispatchGroup.enter()
和 dismissed/popped
vc,应用程序会崩溃吗?基本上,deinit()
会因为 vc 不在内存中而改变结果吗?
例如。这开始了,但在第 3 个后台任务完成之前,vc 被关闭或弹出。 .leave()
只 运行 两次,但应该 运行 3 次。这只是一个简单的例子来理解这个想法:
func viewDidLoad()
let group = DispatchGroup()
// there are 3 background tasks
for task in backgroundTasks {
group.enter()
someBackgroundTask(... completion: { (_) in
group.leave()
})
}
group.notify...
}
不,调用 leave
失败本身不会导致崩溃。 (这里可能不相关,但调用 leave
太多次会崩溃。)
不过,在所有 enter
调用都被 leave
调用抵消之前,调度组不会被释放。更糟糕的是,完成处理程序和 notify
闭包强烈捕获的任何内容都不会被释放。因此,您确实希望确保所有 enter
调用最终都被 leave
调用所抵消。
但我首先建议确认 leave
没有被调用足够的次数。通常会出现完全相反的问题,leave
被调用了正确的次数,但是这些后台任务中的一个或多个在视图控制器被关闭后完成,并且确实不能优雅地处理这种情况。
对于它的价值,如果 someBackgroundTask
正在做一些在视图控制器被关闭后不再需要的事情,我们会:
尽可能将
someBackgroundTask
设为可取消的任务;确保各种闭包不维护对视图控制器的强引用(通过使用
[weak self]
模式),消除强引用循环;如果视图控制器在闭包运行时被释放,请确保闭包能够正常处理,例如
group.notify(queue: .main) { [weak self] in guard let self = self else { return } ... }
和
在视图控制器的
deinit
中(或等效的地方)取消不再需要的任务(同样,假设它是一个可取消的任务)。