如何使用不是主线程的线程,等待 class static Bool 变量为真?
How to use a thread that is NOT the Main thread, to wait until a class static Bool variable is true?
Swift 新手:我通过 DispatchQueue.global(qos: .background).async{ code } 使用 GCD 来执行 HealthKit 查询,在执行每个查询之前我需要等待(通过实现while/sleep 循环)直到 Class static protectedDataEncrypted: Bool(我用它来表示 AppleHealth 数据是否加密且不可访问)为假,我想确保 GCD 永远不会使用 Main (UI) 线程到 check/sleep 静态 protectedDataEncrypted: Bool,因为这将冻结应用程序。
到目前为止我使用的方法有效,但我不是 100% 相信如果 GCD 出于某种原因使用主线程到 check/sleep 静态布尔,它不会死锁,什么按照我下面的代码,这会是比使用睡眠更好的方法吗?
在 AppDelegate 中:我有以下内容:
static var protectedDataEncrypted = false
override func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
AppDelegate.protectedDataEncrypted = false
}
override func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
AppDelegate.protectedDataEncrypted = true
}
在一个单独的 class 中,方法由 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有时它会冻结,如果快速 locking/unlocking 屏幕连续。
到目前为止它有效,但我不相信它会在 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
.
重新安排自己的时间
Swift 新手:我通过 DispatchQueue.global(qos: .background).async{ code } 使用 GCD 来执行 HealthKit 查询,在执行每个查询之前我需要等待(通过实现while/sleep 循环)直到 Class static protectedDataEncrypted: Bool(我用它来表示 AppleHealth 数据是否加密且不可访问)为假,我想确保 GCD 永远不会使用 Main (UI) 线程到 check/sleep 静态 protectedDataEncrypted: Bool,因为这将冻结应用程序。
到目前为止我使用的方法有效,但我不是 100% 相信如果 GCD 出于某种原因使用主线程到 check/sleep 静态布尔,它不会死锁,什么按照我下面的代码,这会是比使用睡眠更好的方法吗?
在 AppDelegate 中:我有以下内容:
static var protectedDataEncrypted = false
override func applicationProtectedDataDidBecomeAvailable(_ application: UIApplication) {
AppDelegate.protectedDataEncrypted = false
}
override func applicationProtectedDataWillBecomeUnavailable(_ application: UIApplication) {
AppDelegate.protectedDataEncrypted = true
}
在一个单独的 class 中,方法由 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有时它会冻结,如果快速 locking/unlocking 屏幕连续。
到目前为止它有效,但我不相信它会在 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
.