如何使用不是主线程的线程,等到类静态Bool变量为真?

问题描述 投票:1回答:1

Swift新手:我正在使用GCD通过DispatchQueue.global(qos:.background).async {code}来执行HealthKit查询,在执行每个查询之前我需要等待(通过while / sleep循环实现),直到Class static protectedDataEncrypted: Bool(我用来表示AppleHealth数据是否加密且无法访问)是错误的,我想确保GCD永远不会使用Main(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%的时间都能正常工作。

提前谢谢了。

swift grand-central-dispatch health-kit ui-thread hkhealthstore
1个回答
2
投票

首先,你不需要自己的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重新安排自己。

© www.soinside.com 2019 - 2024. All rights reserved.