PhotoKit

RSS for tag

Work with image and video assets managed by the Photos app, including those from iCloud Photos and Live Photos, using PhotoKit.

Posts under PhotoKit tag

85 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

Xcode16RC present PHPickerViewController layout error & cell non-Interactive.
After upgrading to Xcode16RC, in an old project based on ObjC, I directly used the following controller code in AppDelegate: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. UIButton *b = [[UIButton alloc]initWithFrame:CGRectMake(100, 100, 44, 44)]; [b setTitle:@"title" forState:UIControlStateNormal]; [self.view addSubview:b]; [b addTarget:self action:@selector(onB:) forControlEvents:UIControlEventTouchUpInside]; } - (IBAction)onB:(id)sender{ PHPickerConfiguration *config = [[PHPickerConfiguration alloc]initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary]; config.preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCurrent; config.selectionLimit = 1; config.filter = nil; PHPickerViewController *picker = [[PHPickerViewController alloc]initWithConfiguration:config]; picker.modalPresentationStyle = UIModalPresentationFullScreen; picker.delegate = self; [self presentViewController:picker animated:true completion:nil]; } - (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results{ } Environment: Simulator iPhone 15 Pro (iOS18) Before this version (iOS17.4), clicking the button to pop up the system photo picker interface was normal (the top boundary was within the SafeAreaGuide area), but now the top boundary of the interface aligns directly to the top of the window, and clicking the photo cell is unresponsive. If I create a new Target, using the same codes, the photo picker page does not have the above problem. Therefore, I suspect it may be due to the old project’s .proj file’s info.plist, buildSetting, or buildPhase lacking some default configuration key value required by the new version, (My project was built years ago may be from iOS13 or earlier ) but I cannot confirm the final cause. iOS18.0 has the additional messages: objc[79039]: Class UIAccessibilityLoaderWebShared is implemented in both /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/AccessibilityBundles/WebCore.axbundle/WebCore (0x198028328) and /Library/Developer/CoreSimulator/Volumes/iOS_22A3351/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 18.0.simruntime/Contents/Resources/RuntimeRoot/System/Library/AccessibilityBundles/WebKit.axbundle/WebKit (0x1980fc398). One of the two will be used. Which one is undefined. AX Safe category class 'SLHighlightDisambiguationPillViewAccessibility' was not found! Has anyone encountered the same issue as me?
1
0
72
6h
Loading images from `PHPickerResult` with `loadFileRepresentation` taking very long time
We are seeing how most of the images loaded from the PHPickerViewController with: result.itemProvider.loadFileRepresentation(forTypeIdentifier: imageType.identifier) take a fraction of a second to load. However, since a few weeks ago, we are seeing more a more images that take minutes, 10 minutes in some cases. This images shouldn't be in iCloud, they are recently taken, the devices have enough free space and we are trying with good network conditions. Are others out there experiencing the same? Any tips to prevent these long times?
1
0
84
17h
Crashes in PHPickerViewController PFAssertionPolicyAbort
Hello! I'm getting crash reports in PHPickerViewController for iOS 17 users only. Can someone point me into the right direction what could be the root cause in my case since it's related to PHPickerViewController? Thread 0 name: Thread 0 Crashed: 0 libsystem_kernel.dylib 0x00000001e7e9342c __pthread_kill + 8 (:-1) 1 libsystem_pthread.dylib 0x00000001fbc32c0c pthread_kill + 268 (pthread.c:1721) 2 libsystem_c.dylib 0x00000001a6d36ba0 abort + 180 (abort.c:118) 3 PhotoFoundation 0x00000001d2420280 -[PFAssertionPolicyAbort notifyAssertion:] + 68 (PFAssert.m:432) 4 PhotoFoundation 0x00000001d2420068 -[PFAssertionPolicyComposite notifyAssertion:] + 160 (PFAssert.m:259) 5 PhotoFoundation 0x00000001d242061c -[PFAssertionPolicyUnique notifyAssertion:] + 176 (PFAssert.m:292) 6 PhotoFoundation 0x00000001d241f7f4 -[PFAssertionHandler handleFailureInFunction:file:lineNumber:description:arguments:] + 140 (PFAssert.m:169) 7 PhotoFoundation 0x00000001d2420c74 _PFAssertFailHandler + 148 (PFAssert.m:127) 8 PhotosUI 0x0000000216b59e30 -[PHPickerViewController _handleRemoteViewControllerConnection:extension:extensionRequestIdentifier:error:completionHandler:] + 1356 (PHPicker.m:1502) 9 PhotosUI 0x0000000216b5a954 __66-[PHPickerViewController _setupExtension:error:completionHandler:]_block_invoke_3 + 52 (PHPicker.m:1454) Crash report: 2024-09-05_18-27-56.7526_+0500-a953eaee085338a690ac1604a78de86e3e49d182.crash
1
0
89
1d
PhotosPicker fail to load Collections tab on iOS 18
When using PhotosPicker in SwiftUI to let users pick a photo, it will fail to load after switching to the "Collections" tab on iOS 18. This issue doesn't occur on iOS 17. Additionally, using PHPickerViewController will still have the same issue. The code is pretty simple: struct ContentView: View { @State private var selection: PhotosPickerItem? = nil var body: some View { VStack { PhotosPicker("Pick photo", selection: $selection) } .padding() } } And I create a repo for this code: https://github.com/JuniperPhoton/PhotosPickerIssueiOS18 This issue has been reported via Feedback app, and the report ID is FB15069998. I tested in the Xcode 16 Beta 6 and iOS 18 Beta 8. However with the Xcode 16 RC and the iOS 18 RC, this issue still exists. Hoping to find out any workaround to resolve this issue. Thanks.
1
0
91
1d
How do I fetch all PHAssets from Photos Library that contain an edit (filter on hasAdjustments)?
I am trying to retrieve all PHAssets from the Photos Library that have been edited. PHAsset contains the "hasAdjustments" boolean variable but I cannot use that in an NSPredicate to filter for edited photos. What is the proper mechanism to filter out non-edited photos? Here is the code I have written that crashes: let formatString = "mediaType = %d && hasAdjustments == YES" let allPhotosOptions = PHFetchOptions() allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)] allPhotosOptions.predicate = NSPredicate(format: formatString, PHAssetMediaType.image.rawValue) allPhotosOptions.includeAssetSourceTypes = [.typeUserLibrary, .typeiTunesSynced, .typeCloudShared] return PHAsset.fetchAssets(with: allPhotosOptions) Thanks, Rick
0
0
136
2w
Sandboxed Electron macOS app can't access Photos library
I have an Electron app built for macOS, and it was distributed via 'Developer ID' for years, it worked well and I was able to access the photos in the system Photos library. Surely I already have the 'NSPhotoLibraryUsageDescription' key in Info.plist. Recently we are trying to publish this app to Mac App Store, so I have to turn on the sandbox, after that the app starts giving XPC errors while accessing the Photos library. The errors look like: PHAuthorizationStatus: Authorized CoreData: XPC: sendMessage: failed #0 CoreData: XPC: Unable to sendMessage: to server ... CoreData: XPC: sendMessage: failed #7 CoreData: XPC: Unable to connect to server with options { NSPersistentHistoryTrackingKey = 1; NSXPCStoreServerEndpointFactory = "<PLXPCPhotoLibraryStoreEndpointFactory: 0x7fc67e8af370>"; skipModelCheck = 1; } CoreData: XPC: Unable to load metadata: Error Domain=NSCocoaErrorDomain Code=134060 "A Core Data error occurred." UserInfo={Problem=Unable to send to server; failed after 8 attempts.} CoreData: fault: Unable to create token NSXPCConnection. NSXPCStoreServerEndpointFactory 0x7fc67e8af370 -newEndpoint returned nil CoreData: error: Failed to create NSXPCConnection It seems the app could detect the current PHAuthorizationStatus which is Authorized, but it can't fetch the photos from the Photos library (using PhotoKit). I learned from here that I could look for errors from the sandboxd daemon, so I did that, here is what I saw: Sandbox: Picture Keeper(32625) deny(1) mach-lookup com.apple.photos.service Violation: deny(1) mach-lookup com.apple.photos.service Process: Picture Keeper [32625] Path: /Applications/Picture Keeper.app/Contents/MacOS/Picture Keeper Load Address: 0x103bd3000 Identifier: com.simplifieditproducts.picturekeepermas Version: 4575 (4.5.75) Code Type: x86_64 (Native) Parent Process: Picture Keeper [1] Responsible: /Applications/Picture Keeper.app/Contents/MacOS/Picture Keeper User ID: 501 Date/Time: 2024-08-26 16:16:14.645 EDT OS Version: macOS 14.5 (23F79) Release Type: User Report Version: 8 MetaData: {"process_path":["Users","Kevin","Projects","Electron","picturekeeper-electron","dist","picturekeeper","mas-dev","Picture Keeper.app","Contents","MacOS","Picture Keeper"],"apple-internal":false,"primary-filter":"global-name","policy-description":"Sandbox","flags":5,"platform-policy":false,"build":"macOS 14.5 (23F79)","process-path":"\/Applications\/Picture Keeper.app\/Contents\/MacOS\/Picture Keeper","responsible-process-path":"\/Applications\/Picture Keeper.app\/Contents\/MacOS\/Picture Keeper","primary-filter-value":"com.apple.photos.service","platform_binary":"no","responsible-process-signing-id":"com.simplifieditproducts.picturekeepermas","hardware":"Mac","target":"com.apple.photos.service","action":"deny","mach_namespace":1,"checker-pid":1,"container":"\/Users\/Kevin\/Library\/Containers\/com.simplifieditproducts.picturekeepermas\/Data","binary-in-trust-cache":false,"team-id":"LU744924UY","process":"Picture Keeper","global-name":"com.apple.photos.service","platform-binary":false,"pid":32625,"summary":"deny(1) mach-lookup com.apple.photos.service","checker":"launchd","responsible-process-team-id":"xxxxx","operation":"mach-lookup","normalized_target":["com.apple.photos.service"],"errno":1,"uid":501,"profile-flags":0,"profile-in-collection":false,"sandbox_checker":"launchd","signing-id":"com.simplifieditproducts.picturekeepermas","release-type":"User"} I believe I already have the necessary entitlements for the Photos library, see: codesign -d --entitlements - /Applications/Picture\ Keeper.app/Contents/MacOS/Picture\ Keeper [Dict] [Key] com.apple.application-identifier [Value] [String] xxxx.com.simplifieditproducts.picturekeepermas [Key] com.apple.developer.team-identifier [Value] [String] xxxx [Key] com.apple.security.app-sandbox [Value] [Bool] true [Key] com.apple.security.application-groups [Value] [Array] [String] xxxx.com.simplifieditproducts.picturekeepermas [Key] com.apple.security.assets.movies.read-only [Value] [Bool] true [Key] com.apple.security.assets.music.read-only [Value] [Bool] true [Key] com.apple.security.assets.pictures.read-write [Value] [Bool] true [Key] com.apple.security.cs.allow-dyld-environment-variables [Value] [Bool] true [Key] com.apple.security.cs.allow-jit [Value] [Bool] true [Key] com.apple.security.cs.allow-unsigned-executable-memory [Value] [Bool] true [Key] com.apple.security.cs.disable-executable-page-protection [Value] [Bool] true [Key] com.apple.security.cs.disable-library-validation [Value] [Bool] true [Key] com.apple.security.device.usb [Value] [Bool] true [Key] com.apple.security.files.bookmarks.app-scope [Value] [Bool] true [Key] com.apple.security.files.bookmarks.document-scope [Value] [Bool] true [Key] com.apple.security.files.downloads.read-only [Value] [Bool] true [Key] com.apple.security.files.user-selected.read-write [Value] [Bool] true [Key] com.apple.security.network.client [Value] [Bool] true [Key] com.apple.security.network.server [Value] [Bool] true [Key] com.apple.security.personal-information.location [Value] [Bool] true [Key] com.apple.security.personal-information.photos-library [Value] [Bool] true By the way, the Photos library related code was built into a .node file (which is a dylib), and it will be loaded by the main executable during runtime. Anything I missed? Thank you!
5
0
389
2w
Can't share Video to Facebook
I have the Facebook SDK version 17.0.2 and xcode 15. Sharing photos and links work fine but when I try sharing videos, I get the following error: Failed to log access with error: access=<PATCCAccess 0x301d12b20> accessor:<<PAApplication 0x301d27e30 identifierType:auditToken identifier:{pid:18440, version:47210}>> identifier:A9159DCD-76B1-4C77-A01E-DA611929B50B kind:intervalEvent timestampAdjustment:0 visibilityState:0 assetIdentifierCount:0 accessCount:0 tccService:kTCCServicePhotos, error=Error Domain=NSCocoaErrorDomain Code=4097 "connection to service with pid 15679 named com.apple.privacyaccountingd" UserInfo={NSDebugDescription=connection to service with pid 15679 named com.apple.privacyaccountingd}
1
0
246
Aug ’24
TransferRepresentation slow transfer for large video files.
Hi, I notice a very slow transfer rate when I try to transfer a file picked via .photosPicker. This happens especially when I try to import a 4k/60fps video. SwiftUI: VStack { Button("Pick a video") { model.isPhotoPickerView = true } .photosPicker(isPresented: $model.isPhotoPickerView, selection: $model.selectedImageList, maxSelectionCount: 1, matching: .videos) .onChange(of: model.selectedImageList, { old, new in model.handlePhotoPicker() }) } View Model to handle Photo Picker action: private class PageModel: ObservableObject { //other methods @MainActor public func handlePhotoPicker() { if selectedImageList.isEmpty { return } guard let item = selectedImageList.first else { return } Task { do { if let video = try await item.loadTransferable(type: VideoTransferable.self) { let file = video.url //video url arrived } } catch { //handle error } } } } Now the VideoTransferable : struct VideoTransferable: Transferable { let url: URL static var transferRepresentation: some TransferRepresentation { FileRepresentation(contentType: .movie) { video in SentTransferredFile(video.url) } importing: { received in //takes too much time to import large 4K video recorded from iPhone's main camera let copy = FileManager.documentsDirectory.appendingPathComponent(FolderType.temp.rawValue).appendingPathComponent("video_\(Int64(Date().timeIntervalSince1970 * 1000)).MOV") if FileManager.default.fileExists(atPath: copy.path) { try FileManager.default.removeItem(at: copy) } try FileManager.default.copyItem(at: received.file, to: copy) return Self.init(url: copy) } } } To my surprise this issue doesn't happen when I use a custom UIViewControllerRepresentable to wrap UIImagePickerController() and setting videoExportPreset property of the picker to AVAssetExportPresetPassthrough Can someone point me out where I am wrong?
1
0
253
Jul ’24
Photos Picker Selection
Hi! I am having a bit of trouble with the Photos Picker. In my app, users are able to select photos to appear in a grid, right in the app. I am using the new Photos Picker with SwiftUI. I want to be able to have my users select the images after they have been added to the View. So I want there to be a select button in the top toolbar on the leading side, and then once the user hits the select button, they can select the photos they want to remove on the grid, just like in the photos app, and then where the button to add photos originally is, there will be a trash icon to remove the selected photos from the grid. How would I do this? I have attached my code below for my view, as well as my PhotoPicker: import PhotosUI struct LifestyleImagePicker: View { @StateObject var imagePicker = ImagePicker() @State private var showingDetail = false @State private var selectedIndex = 0 @State private var isSelecting = false @State private var isAddingPhoto = false let columns = [GridItem(.adaptive(minimum: 100))] var body: some View { NavigationSplitView { VStack { if !imagePicker.images.isEmpty { ScrollView { LazyVGrid(columns: columns, spacing: 3) { ForEach(imagePicker.images.indices, id: \.self) { index in imagePicker.images[index] .resizable() .scaledToFit() .onTapGesture { selectedIndex = index showingDetail = true } } } } } else { Text("Tap the plus icon to add photos to your own Inspo Board.") .multilineTextAlignment(.center) } } .padding() .navigationTitle("Lifestyle") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { PhotosPicker(selection: $imagePicker.imageSelections, maxSelectionCount: 10, matching: .images, photoLibrary: .shared()) { Image(systemName: "photo.badge.plus") .imageScale(.large) } } } } detail: { Text("Pick your lifestyle") } .sheet(isPresented: $showingDetail) { DetailImageView(images: $imagePicker.images, selectedIndex: selectedIndex) } } } #Preview { LifestyleImagePicker() } import PhotosUI import Combine import Foundation @MainActor class ImagePicker: ObservableObject { @Published var image: Image? @Published var images: [Image] = [] @Published var imageSelection: PhotosPickerItem? { didSet { if let imageSelection { Task { try await loadTransferable(from: imageSelection) } } } } @Published var imageSelections: [PhotosPickerItem] = [] { didSet { Task { if !imageSelections.isEmpty { try await loadTransferable(from: imageSelections) imageSelections = [] } } } } func loadTransferable(from imageSelections: [PhotosPickerItem]) async throws { do { for imageSelection in imageSelections { if let data = try await imageSelection.loadTransferable(type: Data.self) { if let uiImage = UIImage(data: data) { self.images.append(Image(uiImage: uiImage)) } } } } catch { print(error.localizedDescription) } } func loadTransferable(from imageSelection: PhotosPickerItem?) async throws { do { if let data = try await imageSelection?.loadTransferable(type: Data.self) { if let uiImage = UIImage(data: data) { self.image = Image(uiImage: uiImage) } } } catch { print(error.localizedDescription) image = nil } } }
1
1
357
Jul ’24
PHPickerViewController in Limited Access photos mode
Dear Experts, In "limited access" photos mode, I present a PHPickerViewController. It shows the entire photo library, with a note at the top saying that the app can only access the items that I select. I select a photo. In the delegate method, I get a PHPickerResult containing a plausible-looking string for the assetIdentifier. It's the same string that I get for that photo in "full access" mode. Should this photo now be accessible, or do I need to do something else at this point? When I call fetchAssetsWithLocalIdentifiers using this assetIdentifier, I get no results. When I call cloudIdentifierMappingsForLocalIdentifiers, I get error PHPhotosErrorIdentifierNotFound. In "full access" mode, both work OK. What am I missing? Thanks.
3
0
503
Jul ’24
How to migrate PHPhotoLibraryChangeObserver to Swift 6?
I have the following code: extension AssetGridViewController: PHPhotoLibraryChangeObserver { func photoLibraryDidChange(_ changeInstance: PHChange) { Task { @MainActor in guard let changes = changeInstance.changeDetails(for: fetchResult) else { return } fetchResult = changes.fetchResultAfterChanges } } } With Swift 6, this generates a compilation error: Main actor-isolated instance method 'photoLibraryDidChange' cannot be used to satisfy nonisolated protocol requirement. The error includes to fix-it suggestions: Adding nonisolated to the function (nonisolated func photoLibraryDidChange(_ changeInstance: PHChange)) Adding @preconcurrency to the protocol conformance (extension AssetGridViewController: @preconcurrency PHPhotoLibraryChangeObserver {) Both options generate a runtime error: EXC_BREAKPOINT (code=1, subcode=0x105b7c400). For context, AssetGridViewController is a regular UIViewController. Any ideas on how to fix this?
2
0
417
Jul ’24
Is it required to update photo metadata to set 1 for Orientation?
I've had an app that edits photos in your library since the PhotoKit API was released in iOS 8. I know it was required if you preserve photo metadata you had to change the value of Orientation to 1 (up), otherwise PhotoKit would fail to perform the asset change request. When I remove this code, I'm seeing Orientation is getting changed to 1 automatically both at root and in the TIFF dictionary (tested with iOS 18). I wanted to confirm this is expected behavior, the system does this for us now? If so, can I remove this code for iOS 15+, or was it a recent iOS version this started happening? Thanks!
0
0
324
Jun ’24
Sort user library assets by date captured instead of recently added
Is it possible to sort the user library assets by date captured? The Photos app in iOS 18 lets you choose between Date Captured and Recently Added and I want to offer that same choice in my app. This seems to always sort them by creation date (which I believe is the same as recently added): let assetCollection = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil).firstObject! let fetchResult = PHAsset.fetchAssets(in: assetCollection, options: PHFetchOptions.imageMediaType())
0
1
336
Jun ’24
API for turning regular photos into spatial photos?
With quite some excitement I read about visionOS 2's new feature to automatically turn regular 2D photos into spatial photos, using machine learning. It's briefly mentioned in this WWDC video: https://developer.apple.com/wwdc24/10166 My question is: Can developers use this feature via an API, so we can turn any image into a spatial image, even if it is not in the device photo library? We would like to download an image from our server, convert it on the visionPro on-the-fly and display it as a spatial photo.
3
1
468
Jun ’24
Add 30 frames per secons in assetWriter
Hello, I have converted UIImage to CVPixelBuffer. I am creating a video writing app. In some cases, the same CVPixelBuffer should last in the video for 2 seconds or more. However, I need to add 30 CVPixelBuffers per second because the video, to work on social media, must be 30 frames per second. The problem is that whenever I try to add frames to long videos, like 50-minute videos, it gives an error. The error is something like "Operation cannot be completed". Give me an example of a loop to add 30 CVPixelBuffers per second to a currently written video. Example: while true { if videoInput.isReadyForMoreMediaData { break } if videoInput.isReadyForMoreMediaData, let buffer = videoProvider.getNextFrame() { adaptor.append(buffer, withPresentationTime: CMTime(value: 1, timescale: 30)) } } I await your response.
0
0
402
Jun ’24