Hello! I'm trying to save videos asynchronously. I've already used performChanges without the completionHandler, but it didn't work. Can you give me an example? Consider that the variable with the file URL is named fileURL. What would this look like asynchronously?
PhotoKit
RSS for tagWork with image and video assets managed by the Photos app, including those from iCloud Photos and Live Photos, using PhotoKit.
Posts under PhotoKit tag
78 Posts
Sort by:
Post
Replies
Boosts
Views
Activity
Hello, I am experiencing an unexpected issue related to PhotosKit, where an occasional crash is occurring in an area it shouldn't. I've provided the crash log below for reference below:
Last Exception Backtrace:
0 CoreFoundation 0x1aa050860 __exceptionPreprocess + 164
1 libobjc.A.dylib 0x1a2363c80 objc_exception_throw + 60
2 CoreFoundation 0x1a9f68218 -[__NSDictionaryM setObject:forKeyedSubscript:] + 1184
3 Photos 0x1c11cb178 -[PHCloudIdentifierLookup _lookupCodeSpecificCloudIdentifierStrings:forIdentifierCode:] + 572
4 Photos 0x1c11cb278 -[PHCloudIdentifierLookup _lookupLocalIdentifiersForIdentifierCode:codeSpecificCloudIdentifierStrings:] + 92
5 Photos 0x1c11cbbec __69-[PHCloudIdentifierLookup lookupLocalIdentifiersForCloudIdentifiers:]_block_invoke + 88
6 CoreFoundation 0x1a9f67d70 NSDICTIONARY_IS_CALLING_OUT_TO_A_BLOCK + 24
7 CoreFoundation 0x1a9f67bec -[__NSDictionaryM enumerateKeysAndObjectsWithOptions:usingBlock:] + 288
8 Photos 0x1c11cbb40 -[PHCloudIdentifierLookup lookupLocalIdentifiersForCloudIdentifiers:] + 488
9 Photos 0x1c125e6e4 -[PHPhotoLibrary(CloudIdentifiers) localIdentifierMappingsForCloudIdentifiers:] + 96
10 Photos 0x1c1104f18 0x1c1101000 + 16152
"exceptionReason" : {"arguments":["-[__NSDictionaryM setObject:forKeyedSubscript:]"],"format_string":"*** %s: key cannot be nil","name":"NSInvalidArgumentException","type":"objc-exception","composed_message":"*** -[__NSDictionaryM setObject:forKeyedSubscript:]: key cannot be nil","class":"NSException"},
The crash can be recreated by calling PHPhotoLibrary.cloudIdentifierMappings(forLocalIdentifiers:) with random identifiers, as demonstrated below:
let cloudIdentifiers = (0...10).map { _ in PHCloudIdentifier(stringValue: UUID().uuidString) } let localIdsMap = PHPhotoLibrary.shared().localIdentifierMappings(for: cloudIdentifiers)
I've noticed that the method seems to crash consistently when an incorrect cloud identifier is input. This is surprising to me since the return type is [PHCloudIdentifier : Result<String, Error>], so I was anticipating an explicit error.
The issue can be reproduced on both Xcode 15.0 & iOS 17.2 and Xcode 14.3.1 & iOS 16.0.
While I'm fairly certain that only valid identifiers are used in my app, I would still like to know if there is a potential way to validate a cloud identifier prior to accessing this method?
Hello, I am experiencing an unexpected issue related to PhotosKit, where an occasional crash is occurring in an area it shouldn't. I've provided the crash log below for reference.
The crash can be recreated by calling PHPhotoLibrary.cloudIdentifierMappings(forLocalIdentifiers:) with random identifiers, as demonstrated below:
let cloudIdentifiers = (0...10).map { _ in PHCloudIdentifier(stringValue: UUID().uuidString) }
let localIdsMap = PHPhotoLibrary.shared().localIdentifierMappings(for: cloudIdentifiers)
I've noticed that the method seems to crash consistently when an incorrect cloud identifier is input. This is surprising to me since the return type is [PHCloudIdentifier : Result<String, Error>], so I was anticipating an explicit error.
The issue can be reproduced on both Xcode 15.0 & iOS 17.2 and Xcode 14.3.1 & iOS 16.0.
While I'm fairly certain that only valid identifiers are used in my app, I would still like to know if there is a potential way to validate a cloud identifier prior to accessing this method?
When I embedded a PhotosPickerView() in popover,
it won't works:
struct PhotoPickerTest: View {
@State private var selectedPhotoItem: PhotosPickerItem?
@State var isTaped: Bool = false
var body: some View {
Button("", systemImage: "plus") {
isTaped = true
}
.popover(isPresented: $isTaped) {
PhotoPickerView()
}
}
func PhotoPickerView() -> some View {
PhotosPicker(selection: $selectedPhotoItem) {
Image(systemName: "photo")
}
}
}
but if I just replace "popover" to "sheet", it works fine:
struct PhotoPickerTest: View {
@State private var selectedPhotoItem: PhotosPickerItem?
@State var isTaped: Bool = false
var body: some View {
Button("", systemImage: "plus") {
isTaped = true
}
.sheet(isPresented: $isTaped) {
PhotoPickerView()
}
}
func PhotoPickerView() -> some View {
PhotosPicker(selection: $selectedPhotoItem) {
Image(systemName: "photo")
}
}
}
I think it's a bug, and bothered me a lot, hope apple engineers can fix it.
Hello,
We have a Photo Vault app. We were hiding users' photos behind a semi-functional calculator. But after rejection, we thought "decoy functionality" meant we needed to remove this fake calculator feature. We removed it, and tried many things to solve this issue, but couldn't understand what Apple wants us to change. We've been trying to contact Apple for more details, but they keep sending the same message every time.
Helps appreciated. Here is the rejection message:
.
Your app uses public APIs in an unapproved manner, which does not comply with guideline 2.5.1 of the App Store Review Guidelines.
Specifically, we found that your app uses a decoy functionality to hide a user’s photos, which is not an appropriate use of the Photos API.
Since there is no accurate way of predicting how an API may be modified and what effects those modifications may have, Apple does not permit unapproved uses of public APIs in App Store apps.
Next Steps
Please revise your app to ensure that documented APIs are used in the manner prescribed by Apple.
It would be appropriate to remove any features in your app that use a decoy functionality to hide a user's photos from your app.
If there are no alternatives for providing the functionality your app requires, you can use Feedback Assistant to submit an enhancement request.
**does anyone know what this is, means, or is affiliated to ? **
I'm running this SwiftUI sample app for photos without any modifications except for adding my developer profile, which is necessary to build it. When I tap on the thumbnail to see the photo library (after granting access to my photo library), I see that some of the thumbnails are stuck in a loading state, and when I tap on thumbnails, I only see a low-resolution image (the thumbnail), not the full-resolution image that should load.
In the console I can see this error that occurs when tapping on a thumbnail to see the full-resolution image:
CachedImageManager requestImage error: The operation couldn’t be completed. (PHPhotosErrorDomain error 3164.)
When I make a few modifications necessary to run the app as a native macOS app, all the thumbnails load immediately, and clicking on them reveals the full-resolution images.
Even with sample code from Apple, the same warning forever.
"Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)""
Failed to log access with error: access=<PATCCAccess 0x28316b070> accessor:<<PAApplication 0x283166df0 identifierType:auditToken identifier:{pid:1456, version:3962}>> identifier:2EE1A54C-344A-40AB-9328-3F8E8B5E8A85 kind:intervalEvent timestampAdjustment:0 visibilityState:0 assetIdentifierCount:0 tccService:kTCCServicePhotos, error=Error Domain=NSCocoaErrorDomain Code=4097 "connection to service with pid 235 named com.apple.privacyaccountingd" UserInfo={NSDebugDescription=connection to service with pid 235 named com.apple.privacyaccountingd}
Entitlements are reviewed.
var config = PHPickerConfiguration()
config.filter = PHPickerFilter.images
I want only 'png' files to be displayed when the PHPickerViewController photo list is opened.
I've read this post : https://developer.apple.com/forums/thread/687415
In this post, it is mentioned that filtering image formats by PHPickerConfiguration is not possible (2 years ago).
Is it still not possible? Has issue 71832162 not been resolved?
From IOS 17.
Have an issue when saving video and reading it from PHPickerViewController. Video become into jpeg file
Code save video and I saw reason because i changed creationDate. But IOS 16 no bug here
doVertifyAccessAblum() {
DispatchQueue.global(qos: .background).async {
if let url = URL(string: videoURL), let urlData = NSData(contentsOf: url) {
let galleryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath="\(galleryPath)/\(url.lastPathComponent).mp4"
DispatchQueue.main.async {
urlData.write(toFile: filePath, atomically: true)
PHPhotoLibrary.shared().performChanges({
let changeRequest = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
changeRequest?.creationDate = Date()
}) { success, error in
LOGGING.debug("Save video with status: success=\(success) error=\(String(describing: error))")
}
}
}
}
}
}
My app uses PHLivePhoto.request to generate live photos, but memory leaks if I use a custom targetSize.
PHLivePhoto.request(withResourceFileURLs: [imageUrl, videoUrl], placeholderImage: nil, targetSize: targetSize, contentMode: .aspectFit) {[weak self] (livePhoto, info) in
Change targetSize to CGSizeZero, problem resolved.
PHLivePhoto.request(withResourceFileURLs: [imageUrl, videoUrl], placeholderImage: nil, targetSize: CGSizeZero, contentMode: .aspectFit) {[weak self] (livePhoto, info) in
In my app I get a UIImage for a PHAsset via PHImageManager.requestImage(for:targetSize:contentMode:options:resultHandler:). I directly display that image in a UIImageView that has preferredImageDynamicRange set to .high. The problem is I do not see the high dynamic range.
I see the HDRDemo23 sample code uses PhotosPicker to get a UIImage from Data through UIImageReader whose config enables prefersHighDynamicRange.
Is there a way to support HDR when using the Photos APIs to request display images?
And is there support for PHLivePhoto displayed in PHLivePhotoView retrieved via PHImageManager.requestLivePhoto?
Using the new inline PhotosPicker style in iOS 17, it isn't made clear how to handle the cancel button's input, and i cannot seem to find an answer in the documentation.
PhotosPicker(
"Select picture",
selection: $selected,
selectionBehavior: .default,
photoLibrary: .shared()
)
.photosPickerStyle(.inline)
Does anybody have a solution or is this a bug that needs to be fixed?
i have received a lot of crash log only in iOS16
the crash occured when i called :
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:resultHandler]
here is the crash log
Exception Type: NSInternalInconsistencyException
ExtraInfo:
Code Type: arm64
OS Version: iPhone OS 16.0 (20A5328h)
Hardware Model: iPhone14,3
Launch Time: 2022-07-30 18:43:25
Date/Time: 2022-07-30 18:49:17
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:Unhandled error (NSCocoaErrorDomain, 134093) occurred during faulting and was thrown: Error Domain=NSCocoaErrorDomain Code=134093 "(null)"
Last Exception Backtrace:
0 CoreFoundation 0x00000001cf985dc4 0x1cf97c000 + 40388
1 libobjc.A.dylib 0x00000001c8ddfa68 0x1c8dc8000 + 96872
2 CoreData 0x00000001d56d2358 0x1d56cc000 + 25432
3 CoreData 0x00000001d56fa19c 0x1d56cc000 + 188828
4 CoreData 0x00000001d5755be4 0x1d56cc000 + 564196
5 CoreData 0x00000001d57b0508 0x1d56cc000 + 935176
6 PhotoLibraryServices 0x00000001df1783e0 0x1df0ed000 + 570336
7 Photos 0x00000001df8aa88c 0x1df85d000 + 317580
8 PhotoLibraryServices 0x00000001df291de0 0x1df0ed000 + 1723872
9 CoreData 0x00000001d574e518 0x1d56cc000 + 533784
10 libdispatch.dylib 0x00000001d51fc0fc 0x1d51f8000 + 16636
11 libdispatch.dylib 0x00000001d520b634 0x1d51f8000 + 79412
12 CoreData 0x00000001d574e0a0 0x1d56cc000 + 532640
13 PhotoLibraryServices 0x00000001df291d94 0x1df0ed000 + 1723796
14 PhotoLibraryServices 0x00000001df291434 0x1df0ed000 + 1721396
15 Photos 0x00000001df8a8380 0x1df85d000 + 308096
16 Photos 0x00000001df89d050 0x1df85d000 + 262224
17 Photos 0x00000001df87f62c 0x1df85d000 + 140844
18 Photos 0x00000001df87ee94 0x1df85d000 + 138900
19 Photos 0x00000001df87e594 0x1df85d000 + 136596
20 Photos 0x00000001df86b5c8 0x1df85d000 + 58824
21 Photos 0x00000001df86d938 0x1df85d000 + 67896
22 Photos 0x00000001dfa37a64 0x1df85d000 + 1944164
23 Photos 0x00000001dfa37d18 0x1df85d000 + 1944856
24 youavideo -[YouaImageManager requestImageDataForAsset:options:resultHandler:] (in youavideo) (YouaImageManager.m:0) 27
25 youavideo -[YouaAlbumTransDataController requstTransImageHandler:] (in youavideo) (YouaAlbumTransDataController.m:0) 27
26 youavideo -[YouaAlbumTransDataController requstTransWithHandler:] (in youavideo) (YouaAlbumTransDataController.m:77) 11
27 youavideo -[YouaUploadTransDataOperation startTrans] (in youavideo) (YouaUploadTransDataOperation.m:102) 19
28 Foundation 0x00000001c9e78038 0x1c9e3c000 + 245816
29 Foundation 0x00000001c9e7d704 0x1c9e3c000 + 268036
30 libdispatch.dylib 0x00000001d51fa5d4 0x1d51f8000 + 9684
31 libdispatch.dylib 0x00000001d51fc0fc 0x1d51f8000 + 16636
32 libdispatch.dylib 0x00000001d51ff58c 0x1d51f8000 + 30092
33 libdispatch.dylib 0x00000001d51febf4 0x1d51f8000 + 27636
34 libdispatch.dylib 0x00000001d520db2c 0x1d51f8000 + 88876
35 libdispatch.dylib 0x00000001d520e338 0x1d51f8000 + 90936
36 libsystem_pthread.dylib 0x00000002544b9dbc 0x2544b9000 + 3516
37 libsystem_pthread.dylib 0x00000002544b9b98 0x2544b9000 + 2968
i can't find the error code 134093 definition
i don't know what's going wrong in iOS16
Would anyone have a hint of why this could happen and how to resolve it?
thanks very much
The sample code in the Apple documentation found in PHCloudIdentifier does not compile in xCode 13.2.1.
Can the interface for identifier conversion be clarified so that the answer values are more accessible/readable. The values are 'hidden' inside a Result enum
It was difficult (for me) to rewrite the sample code because I made the mistake of interpreting the Result type as a tuple. Result type is really an enum.
Using the Result type as the return from library.cloudIdentifierMappings(forLocalIdentifiers: ) and .localIdentifierMappings(
for: )
puts the actual mapped identifiers inside the the enum where they need additional access via a .stringValue message or an evaluation of an element of the result enum.
For others finding the same compile issue, here is a working version of the sample code. This compiles in xCode 13.2.1.
func localId2CloudId(localIdentifiers: [String]) -> [String] {
var mappedIdentifiers = [String]()
let library = PHPhotoLibrary.shared()
let iCloudIDs = library.cloudIdentifierMappings(forLocalIdentifiers: localIdentifiers)
for aCloudID in iCloudIDs {
let cloudResult: Result = aCloudID.value
// Result is an enum .. not a tuple
switch cloudResult {
case .success(let success):
let newValue = success.stringValue
mappedIdentifiers.append(newValue)
case .failure(let failure):
// do error notify to user
}
}
return mappedIdentifiers
}
``` swift func
func cloudId2LocalId(assetCloudIdentifiers: [PHCloudIdentifier]) -> [String] {
// patterned error handling per documentation
var localIDs = [String]()
let localIdentifiers: [PHCloudIdentifier: Result<String, Error>] = PHPhotoLibrary.shared() .localIdentifierMappings(
for: assetCloudIdentifiers)
for cloudIdentifier in assetCloudIdentifiers {
guard let identifierMapping = localIdentifiers[cloudIdentifier] else {
print("Failed to find a mapping for \(cloudIdentifier).")
continue
}
switch identifierMapping {
case .success(let success):
localIDs.append(success)
case .failure(let failure) :
let thisError = failure as? PHPhotosError
switch thisError?.code {
case .identifierNotFound:
// Skip the missing or deleted assets.
print("Failed to find the local identifier for \(cloudIdentifier). \(String(describing: thisError?.localizedDescription)))")
case .multipleIdentifiersFound:
// Prompt the user to resolve the cloud identifier that matched multiple assets.
print("Found multiple local identifiers for \(cloudIdentifier). \(String(describing: thisError?.localizedDescription))")
// if let selectedLocalIdentifier = promptUserForPotentialReplacement(with: thisError.userInfo[PHLocalIdentifiersErrorKey]) {
// localIDs.append(selectedLocalIdentifier)
default:
print("Encountered an unexpected error looking up the local identifier for \(cloudIdentifier). \(String(describing: thisError?.localizedDescription))")
}
}
}
return localIDs
}
I have enabled runtime concurrency warnings to check for future problems concerning concurrency: Build Setting / Other Swift Flags:
-Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks
When trying to call the async form of PHPhotoLibrary.shared().performChanges{} I get the following runtime warning: warning: data race detected: @MainActor function at ... was not called on the main thread in the line containing performChanges.
My sample code inside a default Xcode multi platform app template is as follows:
import SwiftUI
import Photos
@MainActor
class FotoChanger{
func addFotos() async throws{
await PHPhotoLibrary.requestAuthorization(for: .addOnly)
try! await PHPhotoLibrary.shared().performChanges{
let data = NSDataAsset(name: "Swift")!.data
let creationRequest = PHAssetCreationRequest.forAsset()
creationRequest.addResource(with: .photo, data: data, options: PHAssetResourceCreationOptions())
}
}
}
struct ContentView: View {
var body: some View {
ProgressView()
.task{
try! await FotoChanger().addFotos()
}
}
}
You would have to have a Swift data asset inside the asset catalog to run the above code, but the error can even be recreated if the data is invalid.
But what am I doing wrong? I have not found a way to run perform changes, the block or whatever causes the error on the main thread.
PS: This is only test code to show the problem, don't mind the forced unwraps.
For PHPickerViewController, we know we can perform simple filtering by
var config = PHPickerConfiguration()
config.filter = PHPickerFilter.images
But, how about we only want to show images with format JPG & PNG, but excluding GIF? This is because our app doesn't support GIF.
Is it possible to do so?
Hello there!
I am trying to use PHPickerViewController to load videos, but I got a problem: I could load some videos only not all.
I refer to the existing thread - https://developer.apple.com/forums/thread/652695, but dosen't work.
This is the code I persent PHPickerViewController
var config = PHPickerConfiguration()
config.selectionLimit = 1
config.filter = .videos
config.preferredAssetRepresentationMode = .current
let picker = PHPickerViewController(configuration: config)
picker.delegate = self
present(picker, animated: true, completion: nil)
Below is the relevant implementation of the method: func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]):
picker.dismiss(animated: true, completion: nil)
for result in results {
result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { (url, error) in
if let error = error {
print(error)
return
}
guard let url = url else { return }
let fileName = "\(Date().timeIntervalSince1970).\(url.pathExtension)"
let newUrl = URL(fileURLWithPath: NSTemporaryDirectory() + fileName)
try? FileManager.default.copyItem(at: url, to: newUrl)
DispatchQueue.main.async {
self.playVideo(newUrl)
}
}
}
Before I print error in line 5, Xcode printed 3 lines of error:
[AXRuntimeCommon] Unknown client: TestPHPicker
[default] [ERROR] Could not create a bookmark: NSError: Cocoa 257 "The file couldn’t be opened because you don’t have permission to view it." }
Error copying file type public.movie. Error: Error Domain=NSItemProviderErrorDomain Code=-1000 "Cannot load representation of type public.movie" UserInfo={NSLocalizedDescription=Cannot load representation of type public.movie, NSUnderlyingError=0x283a4a610 {Error Domain=NSCocoaErrorDomain Code=4101 "Couldn’t communicate with a helper application." UserInfo={NSUnderlyingError=0x283a48b10 {Error Domain=PHAssetExportRequestErrorDomain Code=2 "(null)" UserInfo={NSUnderlyingError=0x283a4a550 {Error Domain=CloudPhotoLibraryErrorDomain Code=82 "Failed to download CPLResourceTypeOriginal" UserInfo=0x28219b300 (not displayed)}}}}}}
And I print error in line 5:
Error Domain=NSItemProviderErrorDomain Code=-1000 "Cannot load representation of type public.movie" UserInfo={NSLocalizedDescription=Cannot load representation of type public.movie, NSUnderlyingError=0x283a4a610 {Error Domain=NSCocoaErrorDomain Code=4101 "Couldn’t communicate with a helper application." UserInfo={NSUnderlyingError=0x283a48b10 {Error Domain=PHAssetExportRequestErrorDomain Code=2 "(null)" UserInfo={NSUnderlyingError=0x283a4a550 {Error Domain=CloudPhotoLibraryErrorDomain Code=82 "Failed to download CPLResourceTypeOriginal" UserInfo=0x28219b300 (not displayed)}}}}}}
For some videos I can load successfully, and some videos I got error. I don't know why this happened.
I am testing this on an iPhone X iOS 14.0(18A373). Xcode 12.0 (12A7209).
Thanks for help!