import Foundation
import UIKit
import AVFoundation
import Photos
import CoreLocation
@MainActor
class PermissionService: ObservableObject {
@Published var cameraPermissionStatus: AVAuthorizationStatus = .notDetermined
@Published var photoLibraryPermissionStatus: PHAuthorizationStatus = .notDetermined
@Published var locationPermissionStatus: CLAuthorizationStatus = .notDetermined
private let locationManager = CLLocationManager()
init() {
checkPermissions()
}
func checkPermissions() {
checkCameraPermission()
checkPhotoLibraryPermission()
checkLocationPermission()
}
// MARK: - Camera Permission
func checkCameraPermission() {
cameraPermissionStatus = AVCaptureDevice.authorizationStatus(for: .video)
}
func requestCameraPermission(completion: @escaping (Bool) -> Void) {
switch cameraPermissionStatus {
case .authorized:
completion(true)
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { granted in
DispatchQueue.main.async {
self.cameraPermissionStatus = granted ? .authorized : .denied
completion(granted)
}
}
case .denied, .restricted:
showPermissionAlert(for: "Camera")
completion(false)
@unknown default:
completion(false)
}
}
// MARK: - Photo Library Permission
func checkPhotoLibraryPermission() {
photoLibraryPermissionStatus = PHPhotoLibrary.authorizationStatus()
}
func requestPhotoLibraryPermission(completion: @escaping (Bool) -> Void) {
switch photoLibraryPermissionStatus {
case .authorized, .limited:
completion(true)
case .notDetermined:
PHPhotoLibrary.requestAuthorization { status in
DispatchQueue.main.async {
self.photoLibraryPermissionStatus = status
completion(status == .authorized || status == .limited)
}
}
case .denied, .restricted:
showPermissionAlert(for: "Photo Library")
completion(false)
@unknown default:
completion(false)
}
}
// MARK: - Location Permission
func checkLocationPermission() {
locationPermissionStatus = locationManager.authorizationStatus
}
func requestLocationPermission(completion: @escaping (Bool) -> Void) {
switch locationPermissionStatus {
case .authorizedWhenInUse, .authorizedAlways:
completion(true)
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
// Completion will be called via delegate
completion(false)
case .denied, .restricted:
showPermissionAlert(for: "Location")
completion(false)
@unknown default:
completion(false)
}
}
// MARK: - Helper Methods
private func showPermissionAlert(for feature: String) {
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(settingsUrl) else { return }
DispatchQueue.main.async {
let alert = UIAlertController(
title: "\(feature) Access Required",
message: "Please enable \(feature) access in Settings to use this feature.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
alert.addAction(UIAlertAction(title: "Settings", style: .default) { _ in
UIApplication.shared.open(settingsUrl)
})
if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let rootViewController = windowScene.windows.first?.rootViewController {
rootViewController.present(alert, animated: true)
}
}
}
}