Skip to content

Instantly share code, notes, and snippets.

@hellensoloviy
Created February 24, 2026 08:24
Show Gist options
  • Select an option

  • Save hellensoloviy/d3d849eb3c6d306b1003eed2287a020d to your computer and use it in GitHub Desktop.

Select an option

Save hellensoloviy/d3d849eb3c6d306b1003eed2287a020d to your computer and use it in GitHub Desktop.
PermissionManager with examples SwiftUI
import SwiftUI
import UserNotifications
import AVFoundation
import Photos
import CoreLocation
@MainActor
final class PermissionManager: NSObject, ObservableObject, CLLocationManagerDelegate {
// MARK: Published states for UI toggles
@Published var notificationsAuthorized = false
@Published var cameraAuthorized = false
@Published var photoLibraryAuthorized = false
@Published var microphoneAuthorized = false
@Published var locationAuthorized = false
// Location manager for permission request
private var locationManager: CLLocationManager?
// MARK: Initialization
override init() {
super.init()
refreshAllPermissions()
}
// MARK: Refresh all permissions
func refreshAllPermissions() {
Task {
await refreshNotificationStatus()
refreshCameraStatus()
refreshPhotoLibraryStatus()
refreshMicrophoneStatus()
refreshLocationStatus()
}
}
// MARK: Notifications
func refreshNotificationStatus() async {
let settings = await UNUserNotificationCenter.current().notificationSettings()
notificationsAuthorized = settings.authorizationStatus == .authorized || settings.authorizationStatus == .provisional
}
func requestNotifications() async {
let granted = try? await UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge])
notificationsAuthorized = granted ?? false
}
// MARK: Camera
func refreshCameraStatus() {
let status = AVCaptureDevice.authorizationStatus(for: .video)
cameraAuthorized = status == .authorized
}
func requestCamera() {
AVCaptureDevice.requestAccess(for: .video) { granted in
Task { @MainActor in
self.cameraAuthorized = granted
}
}
}
// MARK: Photo Library
func refreshPhotoLibraryStatus() {
let status = PHPhotoLibrary.authorizationStatus()
photoLibraryAuthorized = status == .authorized || status == .limited
}
func requestPhotoLibrary() {
PHPhotoLibrary.requestAuthorization { status in
Task { @MainActor in
self.photoLibraryAuthorized = status == .authorized || status == .limited
}
}
}
// MARK: Microphone
func refreshMicrophoneStatus() {
let status = AVAudioSession.sharedInstance().recordPermission
microphoneAuthorized = status == .granted
}
func requestMicrophone() {
AVAudioSession.sharedInstance().requestRecordPermission { granted in
Task { @MainActor in
self.microphoneAuthorized = granted
}
}
}
// MARK: Location
func refreshLocationStatus() {
let status = CLLocationManager.authorizationStatus()
locationAuthorized = status == .authorizedWhenInUse || status == .authorizedAlways
}
func requestLocation() {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.requestWhenInUseAuthorization()
}
// CLLocationManager Delegate
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
refreshLocationStatus()
}
}
//MARK: - Example
struct SettingsScreenView: View {
@StateObject var permissions = PermissionManager()
var body: some View {
Form {
Section("Permissions") {
Toggle("Notifications", isOn: $permissions.notificationsAuthorized)
.onChange(of: permissions.notificationsAuthorized) { _, newValue in
if newValue == false {
// guide user to settings
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
} else {
Task { await permissions.requestNotifications() }
}
}
Toggle("Camera", isOn: $permissions.cameraAuthorized)
.onChange(of: permissions.cameraAuthorized) { _, newValue in
if newValue == false {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
} else {
permissions.requestCamera()
}
}
Toggle("Photo Library", isOn: $permissions.photoLibraryAuthorized)
.onChange(of: permissions.photoLibraryAuthorized) { _, newValue in
if newValue == false {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
} else {
permissions.requestPhotoLibrary()
}
}
Toggle("Microphone", isOn: $permissions.microphoneAuthorized)
.onChange(of: permissions.microphoneAuthorized) { _, newValue in
if newValue == false {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
} else {
permissions.requestMicrophone()
}
}
Toggle("Location", isOn: $permissions.locationAuthorized)
.onChange(of: permissions.locationAuthorized) { _, newValue in
if newValue == false {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
} else {
permissions.requestLocation()
}
}
}
}
.onAppear {
permissions.refreshAllPermissions()
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
permissions.refreshAllPermissions()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment