Skip to main content

get async images working (kinda)

ID
d9b30e5
date
2023-06-09 06:36:32+00:00
author
Alex Chan <alex@alexwlchan.net>
parent
eadcc63
message
get async images working (kinda)
changed files
5 files, 74 additions, 3 deletions

Changed files

BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj (26201) → BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj (26643)

diff --git a/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj b/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj
index 8d8a948..dbb95b8 100644
--- a/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj
+++ b/BlinkReviewer/BlinkReviewer.xcodeproj/project.pbxproj
@@ -10,6 +10,7 @@
 		94D2C8B92A320E6F00BEE15B /* ReviewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8B82A320E6F00BEE15B /* ReviewState.swift */; };
 		94D2C8BD2A32796500BEE15B /* AlbumHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8BC2A32796500BEE15B /* AlbumHelpers.swift */; };
 		94D2C8BF2A3299BD00BEE15B /* PhotosLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8BE2A3299BD00BEE15B /* PhotosLibrary.swift */; };
+		94D2C8C12A32FCE300BEE15B /* PHAssetImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D2C8C02A32FCE300BEE15B /* PHAssetImage.swift */; };
 		94D750F02A31A796005859E7 /* BlinkReviewerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94D750EF2A31A796005859E7 /* BlinkReviewerApp.swift */; };
 		94D750F42A31A797005859E7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 94D750F32A31A797005859E7 /* Assets.xcassets */; };
 		94D750F72A31A797005859E7 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 94D750F62A31A797005859E7 /* Preview Assets.xcassets */; };
@@ -45,6 +46,7 @@
 		94D2C8B82A320E6F00BEE15B /* ReviewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewState.swift; sourceTree = "<group>"; };
 		94D2C8BC2A32796500BEE15B /* AlbumHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumHelpers.swift; sourceTree = "<group>"; };
 		94D2C8BE2A3299BD00BEE15B /* PhotosLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotosLibrary.swift; sourceTree = "<group>"; };
+		94D2C8C02A32FCE300BEE15B /* PHAssetImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHAssetImage.swift; sourceTree = "<group>"; };
 		94D750EC2A31A796005859E7 /* BlinkReviewer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BlinkReviewer.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		94D750EF2A31A796005859E7 /* BlinkReviewerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlinkReviewerApp.swift; sourceTree = "<group>"; };
 		94D750F32A31A797005859E7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -163,6 +165,7 @@
 				94D7511F2A31B53E005859E7 /* AlbumInfo.swift */,
 				94D751212A31BD8E005859E7 /* PhotoReviewer.swift */,
 				94D7512F2A31DC4A005859E7 /* ThumbnailList.swift */,
+				94D2C8C02A32FCE300BEE15B /* PHAssetImage.swift */,
 			);
 			path = Views;
 			sourceTree = "<group>";
@@ -317,6 +320,7 @@
 				94D751302A31DC4A005859E7 /* ThumbnailList.swift in Sources */,
 				94D751222A31BD8E005859E7 /* PhotoReviewer.swift in Sources */,
 				94D2C8B92A320E6F00BEE15B /* ReviewState.swift in Sources */,
+				94D2C8C12A32FCE300BEE15B /* PHAssetImage.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift (4857) → BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift (4937)

diff --git a/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift b/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift
index 9f79336..9fd36ad 100644
--- a/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift
+++ b/BlinkReviewer/BlinkReviewer/Photos/AssetHelpers.swift
@@ -64,7 +64,7 @@ extension PHAsset {
         let options = PHImageRequestOptions()
         
         // do I still need this?
-        options.isSynchronous = true
+        options.isSynchronous = false
 
         // If i don't set this value, then sometimes I get an error like
         // this in the `info` variable:
@@ -87,6 +87,7 @@ extension PHAsset {
                 contentMode: .aspectFill,
                 options: options,
                 resultHandler: { (result, info) -> Void in
+                    print("Calling resultHandler for \(self.localIdentifier)")
                     image = result!
                 }
             )

BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift (0) → BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift (1919)

diff --git a/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift b/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift
new file mode 100644
index 0000000..44c254d
--- /dev/null
+++ b/BlinkReviewer/BlinkReviewer/Views/PHAssetImage.swift
@@ -0,0 +1,59 @@
+//
+//  PHAssetImage.swift
+//  BlinkReviewer
+//
+//  Created by Alex Chan on 09/06/2023.
+//
+
+import SwiftUI
+import Photos
+
+class PHAssetImage: NSObject, ObservableObject {
+
+    var asset: PHAsset?
+    var size: CGSize
+    
+    @Published var image = NSImage()
+    @Published var isPhotoLibraryAuthorized = false
+
+    init(_ asset: PHAsset?, size: CGSize) {
+        self.asset = asset
+        self.size = size
+        
+        super.init()
+        
+        if let thisAsset = asset {
+            // This implementation is based on code in a Stack Overflow answer
+            // by Francois Nadeau: https://stackoverflow.com/a/48755517/1558022
+            
+            let options = PHImageRequestOptions()
+            
+            // do I still need this?
+            options.isSynchronous = false
+            
+            // If i don't set this value, then sometimes I get an error like
+            // this in the `info` variable:
+            //
+            //      Error Domain=PHPhotosErrorDomain Code=3164 "(null)"
+            //
+            // This means that the asset is in the cloud, and by default Photos
+            // isn't allowed to download assets here.  Apple's documentation
+            // suggests adding this option as the fix.
+            //
+            // See https://developer.apple.com/documentation/photokit/phphotoserror/phphotoserrornetworkaccessrequired
+            options.isNetworkAccessAllowed = true
+            
+            PHCachingImageManager()
+                .requestImage(
+                    for: thisAsset,
+                    targetSize: size,
+                    contentMode: .aspectFill,
+                    options: options,
+                    resultHandler: { (result, info) -> Void in
+                        print("Calling resultHandler for \(thisAsset.localIdentifier)")
+                        self.image = result!
+                    }
+                )
+        }
+    }
+}

BlinkReviewer/BlinkReviewer/Views/PreviewImage.swift (794) → BlinkReviewer/BlinkReviewer/Views/PreviewImage.swift (1035)

diff --git a/BlinkReviewer/BlinkReviewer/Views/PreviewImage.swift b/BlinkReviewer/BlinkReviewer/Views/PreviewImage.swift
index df72bcd..c78ca72 100644
--- a/BlinkReviewer/BlinkReviewer/Views/PreviewImage.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/PreviewImage.swift
@@ -11,13 +11,20 @@ import SwiftUI
 struct PreviewImage: View {
     var asset: PHAsset
     
+    @ObservedObject var image: PHAssetImage = PHAssetImage(nil, size: PHImageManagerMaximumSize)
+    
+    init(asset: PHAsset) {
+        self.asset = asset
+        self.image = PHAssetImage(asset, size: PHImageManagerMaximumSize)
+    }
+    
     var body: some View {
         ZStack {
             VStack {
                 HStack {
                     Spacer()
                         
-                    Image(nsImage: asset.getImage())
+                    Image(nsImage: self.image.image)
                         .resizable()
                         .aspectRatio(contentMode: .fit)
                         .overlay(alignment: Alignment(horizontal: .center, vertical: .top)) {

BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift (3370) → BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift (3377)

diff --git a/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift b/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift
index 05fcbe6..733030e 100644
--- a/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift
+++ b/BlinkReviewer/BlinkReviewer/Views/ThumbnailImage.swift
@@ -13,7 +13,7 @@ import Photos
 /// The image will be expanded to fill the square, and may be clipped
 /// if the original aspect ratio isn't square.
 struct ThumbnailImage: View {
-    var thumbnail: NSImage
+    @State var thumbnail: NSImage
     var state: ReviewState?
     var isFavorite: Bool
     var isSelected: Bool