I want to request some permissions and want to return false unless all permissions have been granted. I get an error: "Unexpected non-void return value in void function"
But I am returning true/false in all circumstances, what is wrong ?
func requestPermissions () -> Bool {
let types: UIRemoteNotificationType = [.alert, .badge, .sound]
UIApplication.shared.registerForRemoteNotifications(matching: types)
let center = UNUserNotificationCenter.current()
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (videoGranted: Bool) -> Void in
if (videoGranted) {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeAudio, completionHandler: { (audioGranted: Bool) -> Void in
if (audioGranted) {
center.requestAuthorization(options: [.alert, .badge, .sound]) { (notificationGranted:Bool, error) -> Void in
if (notificationGranted) {
DispatchQueue.main.async {
return true
print("Video, audio & notifications granted")
}
} else {
return false
print("Rejected notifications")
}
}
}else {
return false
print("Rejected audio")
}
})
} else {
return false
print("Rejected video")
}
})
}
Any help would be very much appreciated ! Thank you.
Alternative Answer:
func requestPermissionss (completion: ((Bool, Bool, Bool)->Void)?) {
let types: UIRemoteNotificationType = [.alert, .badge, .sound]
UIApplication.shared.registerForRemoteNotifications(matching: types)
let center = UNUserNotificationCenter.current()
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (videoGranted: Bool) -> Void in
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeAudio, completionHandler: { (audioGranted: Bool) -> Void in
center.requestAuthorization(options: [.alert, .badge, .sound]) { (notificationGranted:Bool, error) -> Void in
completion?(videoGranted, audioGranted, notificationGranted)
}
})
})
}
The issue is that inside the closure return keyword has nothing to do with the return of requestPermissions() function. It rather means return from the closure, which doesn't actually return anything (because of the -> Void part)
You can pass a closure with three bool parameters to your function like this:
func requestPermissions (completion: ((Bool, Bool, Bool)->Void)?) {
let types: UIRemoteNotificationType = [.alert, .badge, .sound]
UIApplication.shared.registerForRemoteNotifications(matching: types)
let center = UNUserNotificationCenter.current()
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (videoGranted: Bool) -> Void in
if (videoGranted) {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeAudio, completionHandler: { (audioGranted: Bool) -> Void in
if (audioGranted) {
center.requestAuthorization(options: [.alert, .badge, .sound]) { (notificationGranted:Bool, error) -> Void in
if (notificationGranted) {
completion?(true, true, true)
} else {
completion?(true, true, false)
}
}
}else {
completion?(true, false, false)
}
})
} else {
completion?(false, false, false)
}
})
}
Usage:
requestPermissions { (videoGranted, audioGranted, notificationsGranted) in
print("video granted: \(videoGranted)")
print("audio granted: \(audioGranted)")
print("notifications granted: \(notificationsGranted)")
}
Note, that I also removed DispatchQueue.main.async because it has no sense here. Again, return means return from the current scope, not from the outer function.
Edit
Another thing to note is that with your code you won't ask permissions for audio and notifications if permission for video was declined. Not sure if it is intentional or not. If in fact you need to request all three things independently, which I suppose is your case, you should use approach similar to this:
func requestPermissions() {
let types: UIRemoteNotificationType = [.alert, .badge, .sound]
UIApplication.shared.registerForRemoteNotifications(matching: types)
self.requestVideo { videoGranted in
print("video granted: \(videoGranted)")
self.requestAudio { audioGranted in
print("audio granted: \(audioGranted)")
self.requestNotifications { notificationsGranted in
print("notification granted: \(notificationsGranted)")
}
}
}
}
func requestVideo (completion: ((Bool)->Void)?) {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (videoGranted: Bool) -> Void in
completion?(videoGranted)
})
}
func requestAudio (completion: ((Bool)->Void)?) {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeAudio, completionHandler: { (audioGranted: Bool) -> Void in
completion?(audioGranted)
})
}
func requestNotifications (completion: ((Bool)->Void)?) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (notificationGranted:Bool, error) -> Void in
completion?(notificationGranted)
}
}
Basically you ask for the next thing as soon as you're done with previous one and every next one is requested independently no matter what was the choice on previous requests.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With