Reputation: 1219
I have a method which gives me photo auth status.
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
}
I am calling this method in viewDidAppear of a ViewController , but Application is not freezing.
But if I call semaphore.wait when I ask mainQueue explicitly Application is freezing.
DispatchQueue.main.async{
let semaphore = DispatchSemaphore(value: 0)
semaphore.wait()
}
// Above code will freeze the application.
Can I know the reason ?
Upvotes: 2
Views: 5125
Reputation: 3595
A bit late to the party, but it may be useful for others, since nobody explained the real issue here.
Calling semaphore.wait() decreases the counting semaphore. If the counter becomes smaller than zero, wait() blocks the main queue until you signal the semaphore.
Now, you invoke semaphore.signal() in the completion closure, which happens to execute on the main queue. But the main queue is blocked, so it won't call semaphore.signal(). wait() and signal() will wait for each other for eternity -> a guaranteed classic deadlock!
Forget the semaphore, and refactor the photosAuthorizationStatus() method to return the result via a closure, as suggested by Sagar Chauhan.
Upvotes: 1
Reputation: 437552
In your title, you ask:
can I call on semaphore.wait() main thread?
You should avoid blocking the main thread for any reason. Whether wait
for semaphores or dispatch groups, or even synchronously dispatching (e.g., sync
) of anything more than a few milliseconds. You risk having the watchdog process kill your app if you do this at the wrong time, and it results in a horrible UX.
You then go on to ask:
DispatchQueue.main.async { let semaphore = DispatchSemaphore(value: 0) semaphore.wait() }
Above code will freeze the application.
Can I know the reason
That code says “block the main thread waiting for a signal
on this semaphore”. So, until that signal
arrives, the main thread will be blocked. But the main thread should never be blocked because it services, amongst other things, the UI, and your app will freeze if you deadlock the main thread.
Bottom line, never block the main thread.
Upvotes: 3
Reputation: 5823
Create completion closure in method which will call after successful request authorisation completed. See following code.
Make sure your have added permission key "Privacy - Photo Library Usage Description"
in Info.plist file.
func photosAuthorizationStatus(completion: @escaping (PHAuthorizationStatus) -> Void) {
PHPhotoLibrary.requestAuthorization { (status: PHAuthorizationStatus) in
completion(status)
}
}
Use:
self.photosAuthorizationStatus { (status) in
// use your status here
}
Output:
Upvotes: 1