我可以调用semaphore.wait()主线程吗?

时间:2018-06-11 06:04:11

标签: ios swift grand-central-dispatch

我有一种方法可以让我获得照片身份验证状态。

func photosAuthorizationStatus() -> PHAuthorizationStatus {
        var authStatus = PHAuthorizationStatus.notDetermined
        let semaphore = DispatchSemaphore(value: 0)
        PHPhotoLibrary.requestAuthorization { (status: PHAuthorizationStatus) in
            authStatus = status
            semaphore.signal()
        }
        semaphore.wait()
        return authStatus
    }

我在ViewController的viewDidAppear中调用此方法,但Application并未冻结。

但是如果我在明确询问mainQueue时调用semaphore.wait应用程序正在冻结。

DispatchQueue.main.async{
let semaphore = DispatchSemaphore(value: 0)
semaphore.wait()

}

//上面的代码将冻结应用程序。

我能知道原因吗?

3 个答案:

答案 0 :(得分:0)

在方法中创建完成关闭,该方法将在成功请求授权完成后调用。请参阅以下代码。

确保您已在Info.plist文件中添加了权限密钥"Privacy - Photo Library Usage Description"

func photosAuthorizationStatus(completion: @escaping (PHAuthorizationStatus) -> Void) {
    PHPhotoLibrary.requestAuthorization { (status: PHAuthorizationStatus) in
        completion(status)
    }
}

<强> 使用:

self.photosAuthorizationStatus { (status) in
    // use your status here
}

输出:

enter image description here

答案 1 :(得分:0)

在标题中,您询问:

  

我可以调用semaphore.wait()主线程吗?

您应避免由于任何原因阻塞主线程。无论是wait用于信号量还是调度组,甚至是同步调度(例如sync)超过几毫秒的时间。如果您在错误的时间执行看门狗进程,则有可能会杀死您的应用程序,这会导致可怕的用户体验。


然后您继续问:

DispatchQueue.main.async {
   let semaphore = DispatchSemaphore(value: 0)
   semaphore.wait()
}
     

以上代码将冻结应用程序。

     

我能知道原因

该代码说“阻止主线程在此信号量上等待signal”。因此,在signal到达之前,主线程将被阻塞。但是永远不要阻塞主线程,因为它会死锁主线程,因为它会服务UI和其他应用程序,而它会冻结。

底线,切勿阻塞主线程。

答案 2 :(得分:0)

聚会有点晚,但可能对其他人有用,因为这里没有人解释真正的问题。

调用 semaphore.wait() 会减少计数信号量。如果计数器小于零,wait() 会阻塞主队列,直到您向信号量发出信号为止。

现在,您在完成闭包中调用 semaphore.signal(),它恰好在主队列上执行。但是主队列被阻塞了,所以它不会调用 semaphore.signal()。 wait() 和 signal() 将永远等待对方 -> 有保证的经典死锁!

忘记信号量,并按照 Sagar Chauhan 的建议重构 photosAuthorizationStatus() 方法以通过闭包返回结果。

相关问题