swift - 如何使用不是主线程的线程等到类静态 Bool 变量为真?
问题描述
Swift 新手:我通过 DispatchQueue.global(qos: .background).async{ code } 使用 GCD 来执行 HealthKit 查询,在执行每个查询之前我需要等待(通过 while/sleep 循环实现)直到 Class static protectedDataEncrypted: Bool(我用来表示 AppleHealth 数据是否已加密且无法访问)为假,我想确保 GCD 永远不会使用主(UI)线程来检查/休眠静态 protectedDataEncrypted: Bool,因为这将冻结应用程序.
到目前为止,我使用的方法有效,但我不是 100% 相信如果 GCD 出于某种原因使用主线程检查/休眠静态 Bool,它不会死锁,有什么比使用更好的方法睡觉,按照我下面的代码?
在 AppDelegate 中:我有以下内容:
static var protectedDataEncrypted = false
override func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
AppDelegate.protectedDataEncrypted = false
}
override func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
AppDelegate.protectedDataEncrypted = true
}
在具有由 DispatchQueue.global(qos: .background).async{ code } 调用的方法的单独类中,我在执行 HealthKit 查询之前调用了以下方法
func waitTillUnencrypted(){
while (AppDelegate.protectedDataEncrypted){
DispatchQueue.global(qos: .background).sync {
Thread.sleep(forTimeInterval: 2)
}
}
}
注意:使用 DispatchQueue.global(qos: .background).sync 调用 Thread.sleep 似乎可以防止 UI 冻结,而当我只有 Thread.sleep 时,如果连续快速锁定/解锁屏幕,有时它会冻结。
到目前为止它有效,但我不相信它会在 100% 的时间内有效。
提前谢谢了。
解决方案
首先,不需要你自己的protectedDataEncrypted
. 这已经可以直接作为UIApplication.shared.isProtectedDataAvailable
.
你想要的是一个可以停止的队列。所以创建一个队列来处理事情。如果受保护的数据不可用,请将其挂起。
let protectedQueue = DispatchQueue(label: "protected")
if !UIApplication.shared.isProtectedDataAvailable {
protectedQueue.suspend()
}
现在,如果可能,放置在该队列上的任何东西都protectedQueue.dispatchAsync
将立即运行,或者如果没有,则直接排队。
然后你可以像你一样打开和关闭队列。
override func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
protectedQueue.resume()
}
override func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
protectedQueue.suspend()
}
话虽如此,通常最好只是构建您的操作以盲目地尝试执行自己,然后在失败时处理错误,而不是检查您是否认为它会成功。在某些竞争条件下,您可能会成功启动操作,但数据保护可能会在您完成之前启动。你必须处理那个案子。由于您必须处理这种情况,因此您通常应该让该处理程序成为您处理无法访问的方式。
但是在预检检查可能有用的情况下,或者如果它影响用户可见元素,那么上述内容可能很有用。
投票sleep
永远不是答案。即使你想投票(如果可能的话,你应该避免),你也不应该使用Thread.sleep
. 这会捆绑整个线程并阻止其他任何东西使用它。如果您被迫这样做,那么进行投票的方法是重新安排自己的时间dispatchAfter
。
推荐阅读
- java - 在具有自定义操作系统的 android 设备中启动永无止境的后台服务的最佳实践
- javascript - 为什么我的 javascript 测验的所有答案都是错误的?
- java - Java枚举在我的枚举类的静态方法中为空
- mysql - 使用 Cloudformation 创建 Rd
- jmeter - JMeter - 结果分析。响应时间开销问题
- security - iText 和 Shadow 攻击
- python - 二进制搜索 Python 返回无
- css - 本地文件路径在 v-lazy-image 中不起作用
- css - 如何使用伽玛校正在 CSS 中制作颜色渐变?
- angular - 使用角度如何配置服务以便能够与 DI 一起使用