iOS Swift How to open Location Permission popup - ios

var locMgr = INTULocationManager.sharedInstance()
locMgr.requestLocation(withDesiredAccuracy: .city, timeout: 30, delayUntilAuthorized: true,block: {(currentLoc: CLLocation!, achievedAccuracy: INTULocationAccuracy, status: INTULocationStatus) -> Void in
if status == INTULocationStatus.success {
}
else{
}
Used INTULocationManager , Swift 4.1 , iOS 11.1
if first time run this code pop up Location Permission Request
but If I denied, this is not pop up next time.
how to open Permission Pop up?
i create Button
run this code
let locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
but not worked

There isn't any default functionality which will popup the location permission once the user has denied the permission. You need to show an alert to the user that permission is required, and then redirect the user to Settings screen.
Here's the complete code you can use.
Define a function which will check the location permission.
func hasLocationPermission() -> Bool {
var hasPermission = false
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined, .restricted, .denied:
hasPermission = false
case .authorizedAlways, .authorizedWhenInUse:
hasPermission = true
}
} else {
hasPermission = false
}
return hasPermission
}
Now check location permission through this function and show alert if needed.
if !hasLocationPermission() {
let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: UIAlertControllerStyle.alert)
let okAction = UIAlertAction(title: "Settings", style: .default, handler: {(cAlertAction) in
//Redirect to Settings app
UIApplication.shared.open(URL(string:UIApplicationOpenSettingsURLString)!)
})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
}
Also don't forget to import CoreLocation.
Swift 5.3 and iOS 14 version
func hasLocationPermission() -> Bool {
var hasPermission = false
let manager = CLLocationManager()
if CLLocationManager.locationServicesEnabled() {
switch manager.authorizationStatus {
case .notDetermined, .restricted, .denied:
hasPermission = false
case .authorizedAlways, .authorizedWhenInUse:
hasPermission = true
#unknown default:
break
}
} else {
hasPermission = false
}
return hasPermission
}
if !hasLocationPermission() {
let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Settings", style: .default, handler: {(cAlertAction) in
//Redirect to Settings app
UIApplication.shared.open(URL(string:UIApplication.openSettingsURLString)!)
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
}

Swift 5
Once the user denies the permission then the alert is disabled for your app and will not show again.
You can show popup to the user that permission is required.
Here's the complete code you can use
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .notDetermined, .restricted, .denied:
showPermissionAlert()
case .authorizedAlways, .authorizedWhenInUse:
locationManager.startUpdatingLocation()
}
} else {
locationManager.startUpdatingLocation()
}
Now check location permission through this function and show alert if needed.
func showPermissionAlert(){
let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "Settings", style: .default, handler: {(cAlertAction) in
//Redirect to Settings app
UIApplication.shared.open(URL(string:UIApplication.openSettingsURLString)!)
})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.cancel)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
}

if Permission deny by the user then open Permission PopUp
/* func checkLocation() {
if CLLocationManager.authorizationStatus() != .authorizedWhenInUse
{
print("requesting autorization")
locationManager.requestWhenInUseAuthorization()
} else {
print("start updating location")
}
}*/
func askEnableLocationService() ->String {
var showAlertSetting = false
var showInitLocation = false
if CLLocationManager.locationServicesEnabled() {
switch CLLocationManager.authorizationStatus() {
case .denied:
showAlertSetting = true
print("HH: kCLAuthorizationStatusDenied")
case .restricted:
showAlertSetting = true
print("HH: kCLAuthorizationStatusRestricted")
case .authorizedAlways:
showInitLocation = true
print("HH: kCLAuthorizationStatusAuthorizedAlways")
case .authorizedWhenInUse:
showInitLocation = true
print("HH: kCLAuthorizationStatusAuthorizedWhenInUse")
case .notDetermined:
showInitLocation = true
print("HH: kCLAuthorizationStatusNotDetermined")
default:
break
}
}else{
showAlertSetting = true
print("HH: locationServicesDisabled")
}
if showAlertSetting {
let alertController = UIAlertController(title: "xxxxxx", message: "Please enable location service in the settings", preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default) { (action:UIAlertAction!) in
if let url = URL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
}
alertController.addAction(OKAction)
self.window?.rootViewController?.present(alertController, animated: true, completion:nil)
}
if showInitLocation {
return "YES"
}
return "NO"
}

That is default behavior. Once the popup is shown for the first time. The subsequent request will be treated as declined or whatever is selected on first select. However you can implement your own alert and send user directly to setting app to grant location access like below:
//check if user has denied the access on first popup
if !permissionGranted {
let permissionAlert = UIAlertController(title: "Location Access", message: "Requires location access to take advantage of this feature. Please provide location access from settings", preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)
let settingAction = UIAlertAction(title: "Settings", style: .default) { (action) in
guard let appSettingURl = URL(string: UIApplicationOpenSettingsURLString) else { return }
if UIApplication.shared.canOpenURL(appSettingURl) {
UIApplication.shared.open(appSettingURl, options: [:], completionHandler: nil)
}
}
permissionAlert.addAction(cancelAction)
permissionAlert.addAction(settingAction)
present(permissionAlert, animated: true, completion: nil)
}

Complete Solution : (iOS 14+ and also for prior versions)
1)first get authorization status:-
func locationAuthorizationStatus() -> CLAuthorizationStatus {
let locationManager = CLLocationManager()
var locationAuthorizationStatus : CLAuthorizationStatus
if #available(iOS 14.0, *) {
locationAuthorizationStatus = locationManager.authorizationStatus
} else {
// Fallback on earlier versions
locationAuthorizationStatus = CLLocationManager.authorizationStatus()
}
return locationAuthorizationStatus
}
2)Then check for location permission:-
func hasLocationPermission() -> Bool {
var hasPermission = false
let manager = self.locationAuthorizationStatus()
if CLLocationManager.locationServicesEnabled() {
switch manager {
case .notDetermined, .restricted, .denied:
hasPermission = false
case .authorizedAlways, .authorizedWhenInUse:
hasPermission = true
#unknown default:
break
}
} else {
hasPermission = false
}
return hasPermission
}
3)Then show alert
if !hasLocationPermission() {
let alertController = UIAlertController(title: "Location Permission Required", message: "Please enable location permissions in settings.", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Settings", style: .default, handler: {(cAlertAction) in
//Redirect to Settings app
UIApplication.shared.open(URL(string:UIApplication.openSettingsURLString)!)
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
alertController.addAction(cancelAction)
alertController.addAction(okAction)
self.present(alertController, animated: true, completion: nil)
}
CHEERS :) :)

Related

Check of Location permissions set

My iOS app has been rejected by Apple as the app crashes if a user selected "Dont allow" location access. And the proceeds to tap on my Map button.
How can I wrap this button in check to see if the user has given permission, And if not how can I ask for permission again?
//Map Button Action - Opens Maps - Gives choice of Google or Apple maps
#IBAction func googleMapBtn(_ sender: UIButton) {
UIDevice.current.isBatteryMonitoringEnabled = true
let state = UIDevice.current.batteryState
//If user is in Loop - Cant open maps
if state == .charging {
print("In Loop - Cant open maps")
}
//Present Map Options
else {
let alertController = UIAlertController.init(title: "Open Map", message: "", preferredStyle: .alert)
alertController.addAction(UIAlertAction.init(title: "Google Maps", style: .default, handler: { (action) in
self.googleMapsOpen()
}))
alertController.addAction(UIAlertAction.init(title: "Apple Maps", style: .default, handler: { (action) in
self.appleMapsOpen()
}))
alertController.addAction(UIAlertAction.init(title: "Back", style: .default, handler: { (action) in
self.dismiss(animated: true, completion: nil)
}))
self.present(alertController, animated: true) {
}
}
}
The code crashes whenever a user selects a map type Google/Apple and the self.googleMapsOpen() or self.appleMapsOpen() are executed. Specifically is crashed on the let scheme=
func googleMapsOpen(){
print("Google Maps Pressed")
let scheme = "comgooglemaps://?center=\(LocationManager.sharedInstance.location.coordinate.latitude),\(LocationManager.sharedInstance.location.coordinate.longitude)&zoom=15"
self.open(scheme: scheme)
}
func appleMapsOpen(){
print("Apple Maps Pressed")
let scheme = "http://maps.apple.com/?ll=\(LocationManager.sharedInstance.location.coordinate.latitude),\(LocationManager.sharedInstance.location.coordinate.longitude)&zoom=15"
self.open(scheme: scheme)
}
You can do something like this :
func checkLocationPermissionEnabled()
{
if CLLocationManager.locationServicesEnabled()
{
switch(CLLocationManager.authorizationStatus())
{
case .notDetermined, .restricted, .denied:
self.openDeviceLocationSetting()
return
case .authorizedAlways, .authorizedWhenInUse:
//do whatever you want to do with location
return
}
}
else
{
self.openDeviceLocationSetting()
return
}
}
func openDeviceLocationSetting()
{
let alertController = UIAlertController(title: "", message:"For best results, let your device turn on location using Google's location service.", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
UIAlertAction in
self.isAlertShowing = false
let settingsUrl = NSURL(string: UIApplicationOpenSettingsURLString)
if let url = settingsUrl {
UIApplication.shared.openURL(url as URL)
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default) {
UIAlertAction in
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.present(alertController, animated: true, completion: nil)
}

Request Camera Permission Dialog Priming (Prime Permissions) in iOS

What is the most effective way to prompt a User to provide access to the Camera (or other feature), while ensuring the best experience?
When accessing the Camera, iOS must ask the Customer permission to allow access. As we all know, if the Customer says "No" but then changes their mind, there is no way to reverse this decision from within your App. They must go to Settings and follow a number of steps to re-enable access, namely:
Settings -> Privacy -> Camera -> [Your App] -> turn switch on
Permission Priming is an effective way to avoid a situation where your Customer might deny access to a key feature of your app.
On iOS an App is only allowed to trigger the default system permission once per feature. Permission priming is when an app "primes" the Customer with an alert that mimics a system permission.
The benefit to doing this is so that if the Customer opts-out (selects Cancel), the App is still able to ask again in future, until they say yes — at which time the actual system permission is displayed and the Customer is statistically less likely to then change their mind and enter into the negative work flow.
Furthermore, since cameraSelected() performs this workflow, if the user declines, but then at some future point does change their settings, the App will immediately reflect the new permissions without further input (ie. the User could switch to Settings, change permissions, and then switch back to the App).
Here is some Swift 3 code to implement this feature:
[UPDATE: Included is a solution to open a deep-link to Settings where the User can enable camera access, if they have previously denied it.]
[UPDATE 2: Added sample lines for Analytics implementation.]
func cameraSelected() {
// First we check if the device has a camera (otherwise will crash in Simulator - also, some iPod touch models do not have a camera).
if let deviceHasCamera = UIImagePickerController.isSourceTypeAvailable(.camera) {
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authStatus {
case .authorized:
showCameraPicker()
case .denied:
alertPromptToAllowCameraAccessViaSettings()
case .notDetermined:
permissionPrimeCameraAccess()
default:
permissionPrimeCameraAccess()
}
} else {
let alertController = UIAlertController(title: "Error", message: "Device has no camera", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { (alert) in
Analytics.track(event: .permissionsPrimeCameraNoCamera)
})
alertController.addAction(defaultAction)
present(alertController, animated: true, completion: nil)
}
}
func alertPromptToAllowCameraAccessViaSettings() {
let alert = UIAlertController(title: "\"<Your App>\" Would Like To Access the Camera", message: "Please grant permission to use the Camera so that you can <customer benefit>.", preferredStyle: .alert )
alert.addAction(UIAlertAction(title: "Open Settings", style: .cancel) { alert in
Analytics.track(event: .permissionsPrimeCameraOpenSettings)
if let appSettingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.openURL(appSettingsURL)
}
})
present(alert, animated: true, completion: nil)
}
func permissionPrimeCameraAccess() {
let alert = UIAlertController( title: "\"<Your App>\" Would Like To Access the Camera", message: "<Your App> would like to access your Camera so that you can <customer benefit>.", preferredStyle: .alert )
let allowAction = UIAlertAction(title: "Allow", style: .default, handler: { (alert) -> Void in
Analytics.track(event: .permissionsPrimeCameraAccepted)
if AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count > 0 {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { [weak self] granted in
DispatchQueue.main.async {
self?.cameraSelected() // try again
}
})
}
})
alert.addAction(allowAction)
let declineAction = UIAlertAction(title: "Not Now", style: .cancel) { (alert) in
Analytics.track(event: .permissionsPrimeCameraCancelled)
}
alert.addAction(declineAction)
present(alert, animated: true, completion: nil)
}
func showCameraPicker() {
let picker = UIImagePickerController()
picker.delegate = self
picker.modalPresentationStyle = UIModalPresentationStyle.currentContext
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.camera
present(picker, animated: true, completion: nil)
}
Suppose we have two buttons (one for picking picture from library another from camera) with tags 1,2 that are linked to action:
import UIKit
import AVFoundation
#IBAction func changeImage(sender: UIButton) {
let picker = UIImagePickerController()
if sender.tag == 2 { // tag = 2 for camera button. tag = 1 for image picker
guard UIImagePickerController.isSourceTypeAvailable(.camera) else { return }
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
switch cameraAuthorizationStatus {
case .notDetermined:
requestCameraPermission()
return
case .authorized:
break
case .restricted, .denied:
alertCameraAccessNeeded()
return
#unknown default:
return
}
picker.sourceType = .camera
}
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
private func requestCameraPermission() {
AVCaptureDevice.requestAccess(for: .video) { [weak self] accessGranted in
if !accessGranted {
DispatchQueue.main.async {
self?.alertCameraAccessNeeded()
}
}
}
}
private func alertCameraAccessNeeded() {
guard let settingsAppURL = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(settingsAppURL) else { return } // This should never happen
let alert = UIAlertController(
title: "Need Camera Access",
message: "Camera access is required to take pictures of item.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "Cancel", style: .default))
alert.addAction(UIAlertAction(title: "Allow Camera", style: .cancel) { _ in
UIApplication.shared.open(settingsAppURL, options: [:])
})
present(alert, animated: true)
}

CLLocationManager.authorizationStatus results in EXC_BAD_ACCESS code=2

My very first app is working fine so far, if location services are allowed for it.
As soon as I disable the location services for this app in particular (Airplane mode, as well as generally disabled location services are working as expected).
The code is the following:
func locationServices()->Bool{
if CLLocationManager.locationServicesEnabled() {
switch(CLLocationManager.authorizationStatus()) {
case .NotDetermined, .Restricted, .Denied:
return false
case .AuthorizedAlways, .AuthorizedWhenInUse:
return true
}
} else {
return false
}
}
Called from the viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
txtNotes.delegate = self
datePicker.maximumDate = NSDate()
if (inc != nil) {
let Dateformatter = NSDateFormatter()
Dateformatter.dateStyle = NSDateFormatterStyle.MediumStyle
navigationItem.title = Dateformatter.stringFromDate((inc?.date)!)
datePicker.date = (inc?.date)!
txtNotes.text = inc?.notes
ratingControl.rating = (inc?.rating)!
lblAccuracy.text = inc?.geoloc
self.location = inc?.geocor
}
else {
if(locationServices()){
self.locationManager = CLLocationManager()
locationManager!.delegate = self
locationManager!.requestWhenInUseAuthorization()
locationManager!.desiredAccuracy = kCLLocationAccuracyBest
locationManager!.startUpdatingLocation()
}
else{
lblAccuracy.text = "Location Services Disabled"
let alertController = UIAlertController(
title: "Location Services Disabled",
message: "Please allow this application to use location services",
preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
alertController.addAction(cancelAction)
let openAction = UIAlertAction(title: "Open Settings", style: .Default) { (action) in
if let url = NSURL(string:UIApplicationOpenSettingsURLString) {
UIApplication.sharedApplication().openURL(url)
}
}
alertController.addAction(openAction)
self.presentViewController(alertController, animated: true, completion: nil)
viewDidLoad()
}
}
}
Accessing a not yet initialized delegate is not a smart idea...
Initializing prior to accessing it resolved my issue.

Detect when "back to app" is pressed

I've created a function which is suppose to handle the permission with location, so that the app will close if it does not have permission to location. However when you press open settings and press "back to app" in the status bar the determeinePermission method is not being executed again. I've tried to add it to viewDidLoad, viewDidAppear and viewWillAppear. what can I do?
func determinePermission() {
switch CLLocationManager.authorizationStatus() {
case .Authorized:
if CLLocationManager.locationServicesEnabled() {
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
manager.startUpdatingLocation()
}
case .NotDetermined:
manager.requestWhenInUseAuthorization()
case .AuthorizedWhenInUse, .Restricted, .Denied:
let alertController = UIAlertController(
title: "Background Location Access Disabled",
message: "In order to be notified about adorable kittens near you, please open this app's settings and set location access to 'Always'.",
preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
exit(0)
}
alertController.addAction(cancelAction)
let openAction = UIAlertAction(title: "Open Settings", style: .Default) { (action) in
if let url = NSURL(string:UIApplicationOpenSettingsURLString) {
UIApplication.sharedApplication().openURL(url)
}
}
alertController.addAction(openAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
Try adding it to UIApplicationDelegate.applicationDidBecomeActive.

How to check if the user gave permission to use the camera?

Trying to write this:
if usergavepermissiontousercamera
opencamera
else
showmycustompermissionview
Couldn't find a current way to do this simple task.
Note: Should also work iOS7 even if it requires a different method
You can use the following code for doing the same:
if AVCaptureDevice.authorizationStatusForMediaType(AVMediaTypeVideo) == AVAuthorizationStatus.Authorized {
// Already Authorized
} else {
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
if granted == true {
// User granted
} else {
// User rejected
}
})
}
NOTE:
Make sure that you add the AVFoundation Framework in the Link Binary section of build phases
You should write import AVFoundation on your class for importing AVFoundation
SWIFT 3
if AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo) == AVAuthorizationStatus.authorized {
// Already Authorized
} else {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { (granted: Bool) -> Void in
if granted == true {
// User granted
} else {
// User Rejected
}
})
}
Swift 4
if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
//already authorized
} else {
AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
if granted {
//access allowed
} else {
//access denied
}
})
}
The following is a cleaned up answer updated for Swift 4.x:
Starting with iOS 10, you must also request permission in the info.plist file to avoid a crash:
Privacy - Camera Usage Description
You must provide a string that is presented to the user with this key. Failure to do so will result in a crash when attempting to access the camera.
import AVFoundation
func checkCameraAccess() {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .denied:
print("Denied, request permission from settings")
presentCameraSettings()
case .restricted:
print("Restricted, device owner must approve")
case .authorized:
print("Authorized, proceed")
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { success in
if success {
print("Permission granted, proceed")
} else {
print("Permission denied")
}
}
}
}
func presentCameraSettings() {
let alertController = UIAlertController(title: "Error",
message: "Camera access is denied",
preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Cancel", style: .default))
alertController.addAction(UIAlertAction(title: "Settings", style: .cancel) { _ in
if let url = URL(string: UIApplicationOpenSettingsURLString) {
UIApplication.shared.open(url, options: [:], completionHandler: { _ in
// Handle
})
}
})
present(alertController, animated: true)
}
This will test for the four possible answers, and then either request permission if it is notDetermined, or direct the user to settings to enable it if it is denied. If it is restricted, the current user may not be able to enable it, but you should provide some form of guidance to them.
Swift 3.0 Updated Solution
func callCamera(){
let myPickerController = UIImagePickerController()
myPickerController.delegate = self;
myPickerController.sourceType = UIImagePickerControllerSourceType.camera
self.present(myPickerController, animated: true, completion: nil)
NSLog("Camera");
}
func checkCamera() {
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authStatus {
case .authorized: callCamera() // Do your stuff here i.e. callCameraMethod()
case .denied: alertPromptToAllowCameraAccessViaSetting()
case .notDetermined: alertToEncourageCameraAccessInitially()
default: alertToEncourageCameraAccessInitially()
}
}
func alertToEncourageCameraAccessInitially() {
let alert = UIAlertController(
title: "IMPORTANT",
message: "Camera access required for capturing photos!",
preferredStyle: UIAlertControllerStyle.alert
)
alert.addAction(UIAlertAction(title: "Cancel", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Allow Camera", style: .cancel, handler: { (alert) -> Void in
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
}))
present(alert, animated: true, completion: nil)
}
func alertPromptToAllowCameraAccessViaSetting() {
let alert = UIAlertController(
title: "IMPORTANT",
message: "Camera access required for capturing photos!",
preferredStyle: UIAlertControllerStyle.alert
)
alert.addAction(UIAlertAction(title: "Dismiss", style: .cancel) { alert in
if AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count > 0 {
AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo) { granted in
DispatchQueue.main.async() {
self.checkCamera() } }
}
}
)
present(alert, animated: true, completion: nil)
}
This will open the camera when permission is given by the user. Otherwise show alert for asking permission.
func openCamera(){
let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
switch (authStatus){
case .notDetermined, .restricted, .denied:
showAlert(title: "Unable to access the Camera", message: "To enable access, go to Settings > Privacy > Camera and turn on Camera access for this app.")
case .authorized:
alert.dismiss(animated: true, completion: nil)
if(UIImagePickerController .isSourceTypeAvailable(.camera)){
picker.sourceType = .camera
picker.showsCameraControls=true
picker.allowsEditing=true
self.viewController!.present(picker, animated: true, completion: nil)
}
}
}
after this call this function for showing alert
func showAlert(title:String, message:String) {
let alert = UIAlertController(title: title,
message: message,
preferredStyle: UIAlertController.Style.alert)
let okAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alert.addAction(okAction)
let settingsAction = UIAlertAction(title: "Settings", style: .default, handler: { _ in
// Take the user to Settings app to possibly change permission.
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
if UIApplication.shared.canOpenURL(settingsUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
// Finished opening URL
})
} else {
// Fallback on earlier versions
UIApplication.shared.openURL(settingsUrl)
}
}
})
alert.addAction(settingsAction)
self.viewController!.present(alert, animated: true, completion: nil)
}
You can import the AVFoundation framework and use the
authorizationStatus(for:)
method shown below and handle the respective cases.
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized: // The user has previously granted access to the camera.
self.setupCaptureSession()
case .notDetermined: // The user has not yet been asked for camera access.
AVCaptureDevice.requestAccess(for: .video) { granted in
if granted {
self.setupCaptureSession()
}
}
case .denied: // The user has previously denied access.
return
case .restricted: // The user can't grant access due to restrictions.
return
}
I have modified the above answer and removed the initial prompt, since when we want to use device's camera the system is prompting for permissions itself:
func checkPermissions() {
let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
switch authStatus {
case .authorized:
setupCamera()
case .denied:
alertPromptToAllowCameraAccessViaSetting()
default:
// Not determined fill fall here - after first use, when is't neither authorized, nor denied
// we try to use camera, because system will ask itself for camera permissions
setupCamera()
}
}
func alertPromptToAllowCameraAccessViaSetting() {
let alert = UIAlertController(title: "Error", message: "Camera access required to...", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Cancel", style: .default))
alert.addAction(UIAlertAction(title: "Settings", style: .cancel) { (alert) -> Void in
UIApplication.shared.openURL(URL(string: UIApplicationOpenSettingsURLString)!)
})
present(alert, animated: true)
}

Resources