简体   繁体   中英

Change view based on permissions with SwiftUI?

I have coded an application that needs the permissions of the photo library. The worry is that it needs it as soon as the application is launched so it must check at the start of the application the permission granted and if it is not determined, ask for it, wait for the result and change the view again, I've been breaking my head for three days? but I can't do it: Can you help me? Here is my code:

Content view:

    struct ContentView: View {
    var auth = false
    @State var limitedAlert = false
    @State var statusPhoto = 0
    @State var AuthPictStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite)
    var body: some View {
        VStack{}
            .task{
                while true {
                    AuthPictStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite)
                }
            }
            if AuthPictStatus == .authorized {
                CardView(canExecute: true)
            }
            if AuthPictStatus == .denied {
                PhotoLybrairyDenied()
            }
            if AuthPictStatus == .limited {
                CardView(canExecute: true)
                    .onAppear{limitedAlert = true}
                    .alert(isPresented: $limitedAlert) {
                        Alert(
                            title: Text("L'accès au photos est limitées !"),
                            message: Text("Votre autorisations ne nous permets d'accèder a seulement certaines photos ! De se fait, nous ne pouvons pas trier l'intégralité de vos photos !"),
                            primaryButton: .destructive(Text("Continuer malgré tout"), action: {
                                
                            }),
                            secondaryButton: .default(Text("Modifier l'autorisation"), action: { // 1
                                guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
                                            return
                                        }

                                        if UIApplication.shared.canOpenURL(settingsUrl) {
                                            UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                                                print("Settings opened: \(success)") // Prints true
                                            })
                                        }
                                    
                            })
                        )
                    }
                }
            if AuthPictStatus == .notDetermined {
                CardView(canExecute: false)
                    .blur(radius: 5)
                    .disabled(true)
            }
        
        
    }
}

PhotoDeleteApp:

//
//  PhotoDeleteApp.swift
//  PhotoDelete
//
//  Created by Rémy on 09/04/2022.
//

import SwiftUI
import Photos

@main
struct PhotoDeleteApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear{
                    PHPhotoLibrary.requestAuthorization({status in })
                }
        }
    }
}
//
//  PhotoDeleteApp.swift
//  PhotoDelete
//
//  Created by Rémy on 09/04/2022.
//

import SwiftUI
import Photos

@main
struct PhotoDeleteApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear{
                    PHPhotoLibrary.requestAuthorization({status in })
                }
        }
    }
}

I dealt with similar headaches related to photo permissions (I'm on SwiftUI and iOS 14). I did some troubleshooting and found that using a SwiftUIViewDelegate to implement custom authorization status wasnt working as expected. I did a test and selected "only selected photos" (which should make the authorization status .limited ). Except the authorization status wasn't limited, but .authorized , and .denied only when I denied access entirely.

So in my SwiftUI app, I gave up trying to be fancy and used the package Permissions SwiftUI. It provides some documentation on how to customize the message, but it handles the permissions using a sheet making the implementation carefree (It does not address .limited case either or the bug I described with the user selecting limited being actually full access).

My implementation looks like this, and is in my entry point @main , under the first View HomeTabView(homeViewModel: homeViewModel) inside the WindowGroup { }

.JMModal(showModal: $homeViewModel.showingPermissionsSelector, for: [.photo], autoDismiss: true, autoCheckAuthorization: false, restrictDismissal: false)
            .changeHeaderTo("App Permissions")
            .changeHeaderDescriptionTo("Export and Import of images requires photos access.")
            .changeBottomDescriptionTo("Allowing the app to import photos provides the app access to airdropped and saved user photos.")

I suggest you try it out and see if it's good enough for your purposes. To include the Permissions SwiftUI package in your project, go to your Project in the left panel, select "Project", go to "Package Dependencies" on the top bar, press the + button, and search for Permissions SwiftUI, there will be many options but only add PermissionsSwiftUIPhoto . If you need other permissions, there are plenty to choose from.

I have the permissions bound to a "import photos" button (in a subview) hence HomeTabViewModel belongs to parent

Button(action: {
            let authorization = PHPhotoLibrary.authorizationStatus()
            print("switching on image authorization status: \(authorization)")
            switch authorization {
            case .notDetermined:
                parent.homeVM.showingPermissionsSelector = true
            case .restricted:
                parent.homeVM.showingPermissionsSelector = true
            case .denied:
                parent.homeVM.showingPermissionsSelector = true
            case .authorized:
                parent.homeVM.showingImagePicker = true
            case .limited:
                parent.homeVM.showingImagePicker = true // I've never reached this case (bug?)
            @unknown default:
                print("unhandled authorization status")
                break
            }

my homeViewModel (simplified for example)

import SwiftUI

final class HomeTabViewModel: ObservableObject {
    @Published var showingPermissionsSelector = false
    @Published var showingImagePicker         = false
   // @Published var showingLimitedSelector = false // Thought I would need this but I dont because there is no differentiation between .authorized and .denied from my testing
}

but you could have your app do an .onAppear { // check auth status and change $homeViewModel.showingPermissionsSelector based on your code's logic}

I dealt with the same problem you are having Rémy, and on one hand I'm glad I dont have to differentiate between .limited and .authorized since it makes it easier for us, but also it's a bit spooky because it means photo authorization is not quite working as expected on iOS...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM