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

77 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

PHPhotoLibrary.shared().performChanges raised error 3303
I want to modify the photo's exif information, which means putting the original image in through CGImageDestinationAddImageFromSource, and then adding the modified exif information to a place called properties. Here is the complete process: static func setImageMetadata(asset: PHAsset, exif: [String: Any]) { let options = PHContentEditingInputRequestOptions() options.canHandleAdjustmentData = { (adjustmentData) -> Bool in return true } asset.requestContentEditingInput(with: options, completionHandler: { input, map in guard let inputNN = input else { return } guard let url = inputNN.fullSizeImageURL else { return } let output = PHContentEditingOutput(contentEditingInput: inputNN) let adjustmentData = PHAdjustmentData(formatIdentifier: AppInfo.appBundleId(), formatVersion: AppInfo.appVersion(), data: Data()) output.adjustmentData = adjustmentData let outputURL = output.renderedContentURL guard let source = CGImageSourceCreateWithURL(url as CFURL, nil) else { return } guard let dest = CGImageDestinationCreateWithURL(outputURL as CFURL, UTType.jpeg.identifier as CFString, 1, nil) else { return } CGImageDestinationAddImageFromSource(dest, source, 0, exif as CFDictionary) let d = CGImageDestinationFinalize(dest) // d is true, and I checked the content of outputURL, image has been write correctly, it could be convert to UIImage and image is ok. PHPhotoLibrary.shared().performChanges { let changeReq = PHAssetChangeRequest(for: asset) changeReq.contentEditingOutput = output } completionHandler: { succ, err in if !succ { print(err) // 3303 here, always! } } }) }
1
0
112
5d
PHPickerViewController update preselectedAssetIdentifiers
I am trying to recreate the iOS Messages app photo selection UI, where a PHPickerViewController is displayed half screen, with the message text field and a scrolling photo viewer on top. I have that UI mostly working, but cannot figure out how to allow a user to remove an image from my scrolling photo viewer (just like in the iOS Messages app). When the picker is initially displayed, I can show selected images using the preselectedAssetIdentifiers. However, if the user taps the "x" to remove an image from the scrolling photo viewer, there is no way that I have found to update that selection in the picker. I can dismiss/show a new picker with the animated property set to false, but that creates a very apparent bounce in the screen. Are there any ways I am missing to accomplish this? Here is what I have so far:
1
0
185
1w
How to show only Spatial video using UIDocumentPickerViewController
Is there a suitable UTType type to satisfy the need to pick up only SpatialVideo in UIDocumentPickerViewController? I already know that PHPickerFilter in PHPickerViewController can do this, but not in UIDocumentPickerViewController. Our app needs to adapt both of these ways to pick spatial videos So is there anything that I can try in UIDocumentPickerViewController to fulfill such picker functionality?
1
0
196
1w
How to implement Notes-style attachments in TextEditor with movable/deletable images?
I'm trying to create a Notes-like experience in my SwiftUI app where users can: Add photos as inline attachments within a TextEditor Move these attachments around within the text (like they were text characters) Delete attachments Preview attachments in full screen Have the attachments persist with the text content Similar to how Apple Notes handles attachments, where images become part of the text flow and can be manipulated like text characters. Current approach: I've tried using a custom TextEditor with a separate array of attachments, but I'm struggling to make the attachments behave as inline elements that can be moved within the text. RichTextEditor: struct RichTextEditor: View { @State var content: String = "" @State private var isGalleryPresented = false @State var pickedImage: PhotosPickerItem? @State private var selectedImage: UIImage? var body: some View { TextEditor(text: $content) .toolbar { ToolbarItemGroup(placement: .keyboard) { Button { isGalleryPresented = true } label: { Label("Attached", systemImage: "paperclip") } } } .photosPicker(isPresented: $isGalleryPresented, selection: $pickedImage) .onChange(of: pickedImage) { oldItem, newItem in Task { if let pickedImage = pickedImage, let data = try? await pickedImage.loadTransferable(type: Data.self), let loadedImage = UIImage(data: data) { if let imageData = loadedImage.jpegData(compressionQuality: 0.7) { Task { await addPhoto(imageData) } } } } } } private func addPhoto(_ imageData: Data) async { await MainActor.run { let photo = PhotoData(imageData: imageData) content += "\n[image:\(photo.id)]" } } }
2
0
250
1w
Does PHAsset localIdentifier change after device transfer?
Hi, I’m working on a photo backup app. I track the PHAsset localIdentifier to determine which photos have been backed up and which haven’t. Recently, I’ve noticed that two users seem to have experienced the localIdentifier changes after transferring data to a new iPhone using Quick Start. Additionally, others on StackOverflow have mentioned that the localIdentifier sometimes changes after updating the iOS version. https://stackoverflow.com/questions/40094728/phobject-localidentifier-reliability I’d like to confirm the reliability of the localIdentifier after an iOS version upgrade or device transfer. Can I continue using these locally stored localIdentifiers? Or is there another recommended approach, such as using PHCloudIdentifier?
2
0
190
1w
Photo permission dialog not shown when iOS app runs on Mac
According to the docs: The first time your app performs an operation that requires [photo library] authorization, the system automatically and asynchronously prompts the user for it. (https://developer.apple.com/documentation/photokit/delivering-an-enhanced-privacy-experience-in-your-photos-app) I.e. it's not necessary for the app to call PHPhotoLibrary.requestAuthorization. This does seem to be what happens when my app runs on an iPhone or iPad; the prompt is shown. But when it runs on a Mac in "designed for iPad" mode, the permission dialog is not presented. Instead the code continues to see status == .notDetermined. That's today, on macOS 15.3. It may have worked in the past. Is anyone else seeing issues with this? Should I call requestAuthorization explicitly? (Would that actually work?)
0
0
189
2w
Preselect PhotoPickerItems from Image when reopening PhotosPicker
I'm using the PhotosPicker in my SwiftUI project, like it is provided in the sample code (https://developer.apple.com/documentation/photokit/bringing-photos-picker-to-your-swiftui-app). Currently it is set up like that: the app loads the images and stores them in CoreData to MyEntity as binary data. However, when a user wants to update the photos there seems to be no possibility to check if the already stored image is already part of the current MyEntity. This means, there seems to be no possibility to preselect already existing images that were selected in a previous session. Trying to use localIdentifier didn't work either, as it is always nil. Now I'm wondering, if anyone has an idea on how to solve the given issue, or if there is no option to do so. Any information is appreciated. Thanks!
2
0
329
Jan ’25
App crashes after requesting PhotoLibrary limited access
My visionOS requires access to users' personal photos. The trigger mechanism is: when user firstly opens a FooView, a task attached to that FooView and calling let status = PHPhotoLibrary.authorizationStatus(for: .readWrite), if the status is .notDetermined, then calling PHPhotoLibrary.requestAuthorization(for: .readWrite, handler: authCompletionHandler) to let visionOS pop out a window to request Photo access. However, the app crashes every time when user selects Limited Access and the system try to pop out a photo library picker. And btw, I have set Prevent limited photos access alert to Yes, but it shouldn't affect the behavior here I guess. There was a debugger message here: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Presentations are not permitted within volumetric window scenes.' However, the window this view belongs to is a .plain style window (though there were 3D object appearing in the other view of same windowgroup) This is my code snippet if this helps: checkAndUpdatePhotoAuthorization is just a wrapper of PHPhotoLibrary.authorizationStatus(for: .readWrite) private func checkAndUpdatePhotoAuthorization() -> PHAuthorizationStatus { let currentStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite) switch currentStatus { case .authorized: print("Photo library access authorized.") isPhotoGalleryAuthorized = true isPhotoGalleryLimited = false isPhotoGalleryAccessRestricted = false isPhotoGalleryDetermined = true case .limited: print("Photo library access limited.") isPhotoGalleryLimited = true isPhotoGalleryAuthorized = false isPhotoGalleryAccessRestricted = false isPhotoGalleryDetermined = true case .notDetermined: isPhotoGalleryDetermined = false print("Photo library access not determined.") case .denied: print("Photo library access denied.") isPhotoGalleryAuthorized = false isPhotoGalleryLimited = false isPhotoGalleryAccessRestricted = false showSettingsAlert = true isPhotoGalleryDetermined = true case .restricted: print("Photo library access restricted.") isPhotoGalleryAuthorized = false isPhotoGalleryLimited = false isPhotoGalleryAccessRestricted = true showPhotoAuthExplainationAlert = true isPhotoGalleryDetermined = true @unknown default: print("Photo library Unknown authorization status.") isPhotoGalleryAuthorized = false isPhotoGalleryLimited = false isPhotoGalleryAccessRestricted = false isPhotoGalleryDetermined = true } return currentStatus } And then FooView attaches task to fire up checkAndUpdatePhotoAuthorization() var body: some View { EmptyView() } .task { try? await Task.sleep(for: .seconds(1.0)) let status = self.checkAndUpdatePhotoAuthorization() if status == .notDetermined { DispatchQueue.main.async { PHPhotoLibrary.requestAuthorization(for: .readWrite, handler: authCompletionHandler) } } Another thing worth to mention is that SOMETIMES it won't crash when running on a debug build. But it crashes when it comes to TF. Any other idea? Big thanks in advance XCode version: 16.2 beta 3 VisionOS version: 2.2
1
0
362
Jan ’25
Is there a way to filter PHPickerViewController by the creation date of the assets?
Our app filters the photo library to a certain date range for ease of picking photos. However, to do this, we have to require full permissions to the photo library. We would like to use the PHPickerViewController and have it filter the results by the assets creation date? This would allow us to use it. I see other filter options, but not this one. And if it isn't there, is this something that is being thought about or on a roadmap?
1
0
345
Jan ’25
App cannot fetch any resource after a while
Hi everyone, We came an issue that, In some scenarios in our app we cannot fetch any resources from device (Photo and Contact). One case we catched is putting app in background and spending time in other commonly used apps and coming back to our app cause this issue but there is a small chance that get this issue during using the application. In cell, we are trying to fetch the image like this imageFetchTask = Task { let image = await CompositionRoot.shared.photosManager.image(requestType: .imageCollections, forId: photoAsset.photoId) self.photoImageView.image(image) } and inner layers of this code we get the PHAsset and request image PHAsset.firstAsset(for: id) let manager = PHImageManager.default() manager.requestImage(for: asset, targetSize: request.targetSize, contentMode: .aspectFill, options: request.options) { (image, info) in continuation.resume(returning: image) } We figured out that issue not happening only in Photos also Contacts and any web request. So any help according to this situation is well appreciated. Thanks
0
0
256
Dec ’24
Keyboard Navigation Not Working for inline PhotosPicker
We are using inline PhotosPicker introduced with iOS 17.0. The accessbility navigation using touch gestures work fine but the navigation through Keyboard doesn't work properly. The tab/arrow based Keyboard navigation can't move from native app process to inline PhotosUI process or vice versa. This is logged as a high severity bug by our accessibility team. Please look into this. Sample code for repro: https://github.com/saalisumer/AccessibilityIssueInlinePhotoPickerIOS Repro video: https://github.com/saalisumer/AccessibilityIssueInlinePhotoPickerIOS/blob/main/Simulator%20Screen%20Recording%20-%20iPhone%2015%20Pro%20-%202024-12-16%20at%2016.27.48.mp4
1
0
317
Dec ’24
Message from com.apple.photos.backend (PhotoKit) in log
Hello Our application is backing up the user photos to some back end. When retrieving the asset data from the Photo Library, we set the flag 'accessNetworkAllowed' to true to get the assets that might be optimized in iCloud. In the application logs, we can see the message below, and it shows as coming from com.apple.photos.backend (PhotoKit) Missing prefetched properties for PHAssetAdjustmentProperties on <PHAsset: 0x160b1ec00> BCF5688F-F7A7-4196-AFC7-A84E8BD95F3E/L0/001 mediaType=1/0, sourceType=1, (5601x3734), creationDate=2022-01-24 23:36:05 +0000, location=0, hidden=0, favorite=0, adjusted=0 . Fetching on demand on the main queue, which may degrade performance. In particular, the message says 'Fetching on demand on the main queue' but I'm not sure if that means that PhotoKit will fetch on main queue or if that mean that our application is requesting the data on main queue. Anyone could clarify? thanks
1
0
457
Dec ’24
How to add CIFilter to AVCaptureDeferredPhotoProxy
Hello, I m trying to implement deferred photo processing in my photo capture app. After I take a photo, I pass it through a CIFilter, now with the Deferred Photo Processing where would I pass the resulting photo through the CIFilter? Since there is no way for me to know when the system has finished processing a photo. If I have to do it in my app foreground every time, how do I prevent a scenario, where the user takes a photo, heads straight to the Photos App and sees the image without the filter?
2
0
451
Dec ’24
PHPhotoLibrary availability detection/notification
Hi, I'm having difficulties figuring out how I can reliably detect if the macOS system PHPhotoLibrary is available. If I place the system Photo Library on an external drive and then eject it, other apps on startup, such as Photos, will tell me that the library isn't available. How can I replicate this behavior? The only API I can find for this detection on startup is "PHPhotoLibrary.shared().unavailabilityReason". However this always returns nil. Another strange behavior is if I register a PHPhotoLibraryAvailabilityObserver class on startup when the library is available and then eject the drive, I do get a notification via photoLibraryDidBecomeUnavailable, but then directly after the call the app is terminated. This prevents the app to perform any kind of graceful termination. Is this the expected behavior? It would make sense that it's up to the developer to decide what happens if the library becomes unavailable. Thanks
0
0
361
Nov ’24
PHLivePhotoEditingContext.saveLivePhoto results in AVFoundation error -11800 "The operation could not be completed" reason An unknown error occurred (-12815)
When trying to edit some Live Photos, calling PHLivePhotoEditingContext.saveLivePhoto results in the following error: Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12815), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x300d05380 {Error Domain=NSOSStatusErrorDomain Code=-12815 "(null)"}} I was able to replicate it on my device by taking a new Live Photo. Not sure what's wrong with that one specifically, not all Live Photos replicate the issue. I've submitted FB15880825 with a sysdiagnose and a Photos Diagnostics as well. Any ideas what's going on here? It's impacting multiple customers. Thanks!
0
0
374
Nov ’24
How to change PHLivePhoto EXIF metadata
I have an app that allows the user to change a photo’s EXIF metadata. To do this, I request a content editing input, get the full size image, modify its properties, create a content editing output, write the output image to the rendered content URL, then call performChanges on the PHPhotoLibrary creating an asset change request for that asset setting its content editing output. This works as expected for regular photos but Live Photos get turned off converted to a regular photo. To address this, I’m doing something similar by changing the properties of the .photo image in the Live Photo. I detect when the content editing input has a Live Photo, create a Live Photo editing context, set a frame processor that returns the frame’s image after setting its properties to the updated properties when the frame type is photo, then I create the content editing output and save the Live Photo to that output. It modifies the Live Photo successfully, but the metadata is not updated. If you get the full size image again the properties are the original properties. If you look at the EXIF metadata using an app like Metapho it remains unchanged. What am I doing wrong here? Thanks! let imageURL = contentEditingInput.fullSizeImageURL! let inputImage = CIImage(contentsOf: imageURL, options: [.applyOrientationProperty: true])! var metadata: [AnyHashable: Any] = inputImage.properties // Edit the metadata as desired... let editingContext = PHLivePhotoEditingContext(livePhotoEditingInput: contentEditingInput)! editingContext.frameProcessor = { frame, error -> CIImage? in // Edit only the still photo if frame.type == .photo { return frame.image.settingProperties(metadata) } return frame.image } let contentEditingOutput = try await withCheckedThrowingContinuation { continuation in let editingOutput = PHContentEditingOutput(contentEditingInput: contentEditingInput) editingOutput.adjustmentData = adjustmentData editingContext.saveLivePhoto(to: editingOutput) { success, error in if success { continuation.resume(returning: editingOutput) } else { continuation.resume(throwing: error!) } } } try await PHPhotoLibrary.shared().performChanges { let request = PHAssetChangeRequest(for: asset) request.contentEditingOutput = contentEditingOutput }
0
0
359
Nov ’24
LivePhoto not applying on iOS 17+ as live wallpaper
Hi fellow iOS developers! 👋 I've written a Swift code that converts a video (from a URL) into a Live Photo after downloading it. The conversion process seems fine, but when I try to set the generated Live Photo as a wallpaper on iOS 17+, it shows the message 'Motion not Available.' Has anyone else experienced this issue or know why this might be happening? Could it be related to changes in iOS 17 Live Photo handling or the generated file structure? Any help or suggestions would be greatly appreciated! 🙏
1
1
363
Nov ’24
PhotosPickerItem loadTransferable Progress is always indeterminate
I tried several times to use the PhotosPickerItem loadTransferable function with the goal of receiving some progress value especially when loading large video media. However, the Progress object returned by the function has always isIndeterminate == true and so doesn't have any progress value to observe. Is there some way to make it work ? Some configuration I might have overlooked ? Or is it just not working I might have to revert back to the UIKit photo picker because of this
1
1
454
Nov ’24
PHAssetCollectionChangeRequest.removeAssets Does Not Work
Hello! I am trying to remove a photo from my Photos Library using PhotosUI. I run into this error when I attempt to delete it: "Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)"" No photos access scope requirements declared for changes Failed to log access with error: access= accessor:<> identifier:82068C12-FD10-4DE2-9867-B4406FBFB706 kind:intervalEvent timestampAdjustment:0 visibilityState:0 assetIdentifierCount:0 accessCount:0 tccService:kTCCServicePhotos, error=Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.privacyaccountingd" UserInfo={NSDebugDescription=connection to service named com.apple.privacyaccountingd}
2
0
436
Nov ’24