我有一种方法可以让我获得照片身份验证状态。
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()
}
//上面的代码将冻结应用程序。
我能知道原因吗?
答案 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
}
输出:
答案 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() 方法以通过闭包返回结果。