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

Ios 我可以调用semaphore.wait()主线程吗?,ios,swift,grand-central-dispatch,Ios,Swift,Grand Central Dispatch,我有一个方法,让我的照片身份 func photosAuthorizationStatus() -> PHAuthorizationStatus { var authStatus = PHAuthorizationStatus.notDetermined let semaphore = DispatchSemaphore(value: 0) PHPhotoLibrary.requestAuthorization { (status: PHAu

我有一个方法,让我的照片身份

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的ViewDidEmerge中调用此方法,但应用程序并没有冻结

但若我在显式询问mainQueue时调用semaphore.wait,那个么应用程序将冻结

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

}
//上述代码将冻结应用程序


我可以知道原因吗?

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

确保您已在Info.plist文件中添加了权限密钥
“隐私-照片库使用说明”

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

输出:


在你的标题中,你会问:

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

您应该避免由于任何原因阻塞主线程。无论是
等待
信号量还是调度组,甚至是同步调度(例如)超过几毫秒的任何内容。如果你在错误的时间这样做,你就有可能让看门狗进程杀死你的应用程序,这会导致糟糕的用户体验


然后你继续问:

上述代码将冻结应用程序

我能知道原因吗

该代码表示“阻止主线程等待此信号量上的
信号”。因此,在
信号到达之前,主线程将被阻塞。但是主线程永远不应该被阻塞,因为如果你死锁主线程,它会为用户界面和应用程序提供服务


底线是,永远不要阻挡主线。

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

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

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


忘记信号量,重构photoAuthorizationStatus()方法,通过闭包返回结果,正如Sagar Chauhan所建议的那样。

您必须已经授予权限,因此对
requestAuthorization
的调用会立即返回,并且信号量不会明显冻结。⚠️️ 如果在主线程中执行此操作,整个应用程序将冻结⚠️️ 这篇文章可能会帮助你。。。如果未请求和已请求场景,是否有简单的方法获取照片身份验证状态。使用完成处理程序,而不是信号量。我知道这一点,但如果我请求,我的代码也不会冻结应用程序。我也可以知道原因吗?@santhosh它不会冻结,因为您已经授予了权限。删除应用程序并重新安装,以便再次请求权限,您的应用程序将冻结。不,这是第一次,它也没有冻结。@santhosh,它正在工作,您可以看到我更新的答案。应用程序首次请求权限并冻结,直到用户交互。
self.photosAuthorizationStatus { (status) in
    // use your status here
}
DispatchQueue.main.async {
   let semaphore = DispatchSemaphore(value: 0)
   semaphore.wait()
}