0

I'm trying to get a view to show in SwiftUI if the user has not given permission for access to the PhotoLibrary (Giving them instructions to allow access to the Photo Library, either with a prompt or to go into Settings and fix the status). Now I'm assuming that PHPhotoLibrary.authorizationStatus is my source of truth, but maybe I haven't fully understood the concept

 var canAccessPhotos : Bool {
        return PHPhotoLibrary.authorizationStatus() == .authorized
 }

...

.sheet(isPresented: canAccessPhotos) { //Error: Cannot convert value of type 'Bool' to expected argument type 'Binding<Bool>'
     AccessPhotoLibraryView() //New View I want to show the user with instructions or prompt
}

Now that doesn't work because canAccessPhotos is not bindable, but I also can't put a @Binding on a computed property and there's currently no mechanism for the variable to update when authorizationStatus changes, so I'm stuck on the next bit on how to solve it.

How do I get the property from PHPhotoLibrary to automatically show the view if/when it changes. Or is there a different way to do it and I've gone in the wrong direction?

Thank you in advanced

Louis Cremen
  • 764
  • 7
  • 12

1 Answers1

0

Ok, you'd better use a coordinator (or a view model) for this problem. Have a look at the code below and let me know if it works for you.

class Coordinator: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {

    @Published var isPhotoLibraryAuthorized = false

    override init() {
        super.init()
        PHPhotoLibrary.shared().register(self)
        updateStatus()
    }

    func photoLibraryDidChange(_ changeInstance: PHChange) {
        updateStatus()
    }

    private func updateStatus() {
        DispatchQueue.main.async {
            self.isPhotoLibraryAuthorized = PHPhotoLibrary.authorizationStatus() == .authorized
        }
    }
}

struct ContentView: View {

    @EnvironmentObject var coordinator: Coordinator

    var body: some View {
        Group {
            if coordinator.isPhotoLibraryAuthorized {
                // some view
            } else {
                // another view
            }
        }
    }
}
Cuneyt
  • 931
  • 5
  • 11
  • Almost. I had to initialise the coordinator in the SceneDelegate and pass it as an environmentObject, and then it looked like something happened in the background as I'm getting a background thread warning. But this is fantastic - thank you for your help – Louis Cremen May 25 '20 at 04:49
  • Perfect! I have updated the code (the authorization status was updating in a different thread, so I have asynchronously updated it in the main thread), it should work fine now :) – Cuneyt May 25 '20 at 04:52
  • By the way, please consider choosing this answer as the right one if it solves your problem :) – Cuneyt May 25 '20 at 04:53