Skip to main content

Handle the Photos Library auth flow properly

ID
9175fdb
date
2023-06-10 08:43:23+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
954fda1
message
Handle the Photos Library auth flow properly

Previously we'd try to look at the fetched data as soon as we got auth,
which caused an index out of bounds error -- trying to get the 0'th item
of an empty list of assets.  Now, we wait until the data is available
before trying to render any views.
changed files
2 files, 25 additions, 23 deletions

Changed files

BlinkReviewer/BlinkReviewer/Photos/PhotosLibrary.swift (6798) → BlinkReviewer/BlinkReviewer/Photos/PhotosLibrary.swift (6767)

diff --git a/BlinkReviewer/BlinkReviewer/Photos/PhotosLibrary.swift b/BlinkReviewer/BlinkReviewer/Photos/PhotosLibrary.swift
index d1a7c6c..6c796e1 100644
--- a/BlinkReviewer/BlinkReviewer/Photos/PhotosLibrary.swift
+++ b/BlinkReviewer/BlinkReviewer/Photos/PhotosLibrary.swift
@@ -18,27 +18,23 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
     @Published var rejectedAssets: PHFetchResult<PHAsset> = PHFetchResult()
     @Published var needsActionAssets: PHFetchResult<PHAsset> = PHFetchResult()
     
-    private let approved = getAlbum(withName: "Approved")
-    private let rejected = getAlbum(withName: "Rejected")
-    private let needsAction = getAlbum(withName: "Needs Action")
+    private lazy var approved = getAlbum(withName: "Approved")
+    private lazy var rejected = getAlbum(withName: "Rejected")
+    private lazy var needsAction = getAlbum(withName: "Needs Action")
     
     override init() {
         super.init()
         PHPhotoLibrary.shared().register(self)
-        updateStatus(isChange: false)
+        getInitialData()
     }
     
-    func updateAsset(atIndex index: Int) {
-//        self.assets[index] = PHAsset.fetchAssets(withLocalIdentifiers: [self.assets[index].localIdentifier], options: nil).firstObject!
-    }
-
     func photoLibraryDidChange(_ changeInstance: PHChange) {
-        print("--> calling photoLibraryDidChange \(changeInstance.description)")
-        print(changeInstance.description)
-        updateStatus(changeInstance)
-    }
-    
-    private func updateStatus(_ changeInstance: PHChange) {
+        // If we've just received permission to read the user's Photos Library, go
+        // ahead and populate all the initial data structures.
+        if !self.isPhotoLibraryAuthorized && PHPhotoLibrary.authorizationStatus() == .authorized {
+            getInitialData()
+        }
+        
         DispatchQueue.main.async {
             let start = DispatchTime.now()
             var elapsed = start
@@ -91,7 +87,7 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
     }
 
 
-    private func updateStatus(isChange: Bool) {
+    private func getInitialData() {
         DispatchQueue.main.async {
             let start = DispatchTime.now()
             var elapsed = start
@@ -111,15 +107,19 @@ class PhotosLibrary: NSObject, ObservableObject, PHPhotoLibraryChangeObserver {
             options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
             options.fetchLimit = 500
             
-            self.assets2 = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
+            self.isPhotoLibraryAuthorized = PHPhotoLibrary.authorizationStatus() == .authorized
+            
+            if (self.isPhotoLibraryAuthorized) {
+                self.assets2 = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
 
-            self.approvedAssets = PHAsset.fetchAssets(in: self.approved, options: nil)
-            self.rejectedAssets = PHAsset.fetchAssets(in: self.rejected, options: nil)
-            self.needsActionAssets = PHAsset.fetchAssets(in: self.needsAction, options: nil)
+                self.approvedAssets = PHAsset.fetchAssets(in: self.approved, options: nil)
+                self.rejectedAssets = PHAsset.fetchAssets(in: self.rejected, options: nil)
+                self.needsActionAssets = PHAsset.fetchAssets(in: self.needsAction, options: nil)
+            }
             
             printElapsed("get all photos data (new)")
             
-            self.isPhotoLibraryAuthorized = PHPhotoLibrary.authorizationStatus() == .authorized
+            
         }
     }
     

BlinkReviewer/BlinkReviewer/Views/PhotoReviewer.swift (10497) → BlinkReviewer/BlinkReviewer/Views/PhotoReviewer.swift (10606)

diff --git a/BlinkReviewer/BlinkReviewer/Views/PhotoReviewer.swift b/BlinkReviewer/BlinkReviewer/Views/PhotoReviewer.swift
index 20e5ee6..362a182 100644
--- a/BlinkReviewer/BlinkReviewer/Views/PhotoReviewer.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/PhotoReviewer.swift
@@ -33,7 +33,11 @@ struct PhotoReviewer: View {
     @ObservedObject var focusedAssetImage = PHAssetImage(nil, size: PHImageManagerMaximumSize, deliveryMode: .highQualityFormat)
     
     var body: some View {
-        if photosLibrary.isPhotoLibraryAuthorized {
+        if !photosLibrary.isPhotoLibraryAuthorized {
+            Text("Waiting for Photos Library authorization…")
+        } else if photosLibrary.assets2.count == 0 {
+            Text("Waiting for Photos Library data…")
+        } else {
             ZStack {
                 VStack {
                     NewThumbnailList(focusedAssetIndex: $focusedAssetIndex)
@@ -74,8 +78,6 @@ struct PhotoReviewer: View {
             .onChange(of: focusedAsset) { newFocusedAsset in
                 focusedAssetImage.asset = newFocusedAsset
             }
-        } else {
-            Text("Waiting for Photos Library authorization…")
         }
     }