[PHPicker] Permission error followed by "no such file" error

I have a naive implementation of the new PHPicker in SwiftUI (code below). When running on a separate device (iPhone 6s, iOS 14.0), I am able to load some images, but not others.

The images that do not load seem to encounter a permissions error:

Code Block
// [...] indicates redacted content for brevity
[...] [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." }
[...] [claims] Upload preparation for claim [...] completed with error: Error Domain=NSCocoaErrorDomain Code=260 "The file “[...].jpeg” couldn’t be opened because there is no such file." UserInfo={NSURL=[...]{Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}


I'm a little confused because I thought a core value proposition of the new PHPicker was that it automatically allowed access to selected photos.

When I try selecting an image using Simulator, I just get the second error (does not exist), but not the first.

I'm also noticing that the main photos grid does not seem to automatically update with new photos, even though the "Recent" album does. I have to force quit and restart the app to see the latest photos appear, though I have not been able to load any of them due to the issue described above.

Code Block swift
//
// PhotoPicker.swift
// NewParis
//
// Created by Yihwan Kim on 7/12/20.
//
import SwiftUI
import UIKit
import PhotosUI
struct PhotoPicker: UIViewControllerRepresentable {
  @Binding var isPresented: Bool
  @Binding var selectedImage: Image?
   
  func makeUIViewController(context: Context) -> PHPickerViewController {
    var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
     
    configuration.filter = .images
     
    let controller = PHPickerViewController(configuration: configuration)
    controller.delegate = context.coordinator
    return controller
  }
   
  func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { }
   
  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }
   
  class Coordinator: PHPickerViewControllerDelegate {
    private let parent: PhotoPicker
     
    init(_ parent: PhotoPicker) {
      self.parent = parent
    }
     
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
      parent.isPresented = false
       
      if let itemProvider = results.first?.itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
        itemProvider.loadObject(ofClass: UIImage.self) { [weak self] uiImage, error in
          DispatchQueue.main.async {
            guard let self = self, let uiImage = uiImage as? UIImage else { return }
            self.parent.selectedImage = Image(uiImage: uiImage)
          }
        }
      }
    }
  }
}


Post not yet marked as solved Up vote post of yihwan Down vote post of yihwan
4.2k views

Answers

Thanks for asking! We are aware of this issue (64630315) and it will be fixed in a future release.

To workaround the permission error for now, you need to reset your simulator / device.
Beta 3 have same issue. PHPicker Demo throughs same error with Xcode beta 3 and iOS beta 3.

Code Block
[ERROR] Could not create a bookmark: NSError: Cocoa 257 "The file couldn’t be opened because you don’t have permission to view it." }
[claims] Upload preparation for claim 5C062BA9-85BE-458E-8DDC-0CBB1FDE4E4F completed with error: Error Domain=NSCocoaErrorDomain Code=260 "The file “D843997F-8362-4A9A-ADAC-7F4DFC889C41.jpeg” couldn’t be opened because there is no such file." UserInfo={NSURL=file:///private/var/mobile/Containers/Shared/AppGroup/26E08B60-0C4E-45B5-85B9-87F4D5F0DDB0/File%20Provider%20Storage/D843997F-8362-4A9A-ADAC-7F4DFC889C41.jpeg, NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/26E08B60-0C4E-45B5-85B9-87F4D5F0DDB0/File Provider Storage/D843997F-8362-4A9A-ADAC-7F4DFC889C41.jpeg, NSUnderlyingError=0x2834f2610 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}





I'm having the same issue here.

I found out a temporary fix (I'm running on Beta 1):
If you manually copy the file to '/Users/username/Library/Developer/CoreSimulator/Devices/B20BF74D-1CB2-497A-9FA5-0752FD1020DB/data/Containers/Shared/AppGroup/BF5086D7-493D-4EA0-B60C-C85BBEFB550F/File Provider Storage/9A11AF58-870C-413B-9EEB-E5A2133296CB.jpeg' then it works.
I'm still seeing this issue in Xcode 12 beta 6 / iPadOS 14.0 beta 18A5373a. This seems like an extremely critical issue for the new photo picker feature - I wouldn't feel confident using the new framework at all if this isn't fixed before the official iOS 14 release.
@julsh, 64630315 has been fixed.

There is a separate JEPG transcoding issue that only affects the simulator (63426347), please refer to https://developer.apple.com/forums/thread/658135 for more information.
This issue is still occurring on iOS 14.0.1
But don't occurring on iOS14.0.

I running on iPhoneXs
Code Block swift
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
guard let provider = results.first?.itemProvider else { return }
guard let typeIdentifer = provider.registeredTypeIdentifiers.first else { return }
provider.loadItem(forTypeIdentifier: typeIdentifer, options: nil) { (urlObject, error) in {
// error
}
}


Please check again.
loadItem isn’t designed for this use case. Please use loadFileRepresentation or loadObjectOfClass instead. NSItemProvider.h has detailed explanation about the difference between them.
Same error when I try to load every image which was not previously loaded by this app :
Code Block Swift
[ERROR] Could not create a bookmark: NSError: Cocoa 257 "The file couldn’t be opened because you don’t have permission to view it."

Picker delegate :
Code Block Swift
public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
for result in results {
let provider = result.itemProvider
if provider.canLoadObject(ofClass: UIImage.self) {
provider.loadObject(ofClass: UIImage.self) { [weak self] image, error in
DispatchQueue.main.async {
guard let self = self, let uiImage = image as? UIImage else { return }
// Do something with 'uiImage'
}
}
}
}
}

The error is displayed when this part of code is called :
Code Block Swift
let uiImage = image as? UIImage


I don't have the error on the simulator, only on real device.

Configuration :
Xcode 12.0.1
iPohne XS Max 14.0.1


Was this ever resolved?
@mredig : No, and I didn't find any solution
@Hdtrs, you should get the UIImage object before the completion handler returns (outside the dispatch async).

The original issue has been resolved. Please create another problem if you have additional questions. Thanks!
Bug is still alive.
Env: iPad 7-gen, iPad OS 14.2


Code Block swift
itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { [weak self] (data, error) in
guard let data = data else {
self?.parent.isPresented = false
return
}
if let error = error {
self?.parent.isPresented = false
}
let sourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
guard let source = CGImageSourceCreateWithData(data as CFData, sourceOptions) else {
return
}
let downsampleOptions = [
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceThumbnailMaxPixelSize: 1024,
] as CFDictionary
guard let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions) else {
return
}
let destinationData = NSMutableData()
guard let imageDestination = CGImageDestinationCreateWithData(destinationData, kUTTypeJPEG, 1, nil) else {
return
}
// Don't compress PNGs, they're too pretty
let isPNG: Bool = {
guard let utType = cgImage.utType else { return false }
return (utType as String) == UTType.png.identifier
}()
let destinationProperties = [
kCGImageDestinationLossyCompressionQuality: isPNG ? 1.0 : 0.75
] as CFDictionary
CGImageDestinationAddImage(imageDestination, cgImage, destinationProperties)
CGImageDestinationFinalize(imageDestination)
DispatchQueue.main.async {
self?.parent.pickedPhoto = destinationData as Data
}
}


I had a lot of "fun" finding a solution for this one. As explained by the Frameworks Engineer, the problem lies in Apple's JPEG transcoding. You actually ask for an "Image" representation, and here lies the issue.

In the Simulator example images, they are helpful in providing multiple image formats. One includes a ".heic" file, that's not a JPEG. And this is the one that usually borks.

My solution is going through all the provided representations for every photo, figure out what it is, and only transcode as a last resort. With this, I haven't had any No such file or directory since then.

Code Block
let supportedRepresentations = [UTType.rawImage.identifier,
                                UTType.tiff.identifier,
                                UTType.bmp.identifier,
                                UTType.png.identifier,
                                UTType.heif.identifier,
                                UTType.heic.identifier,
                                UTType.jpeg.identifier,
                              UTType.webP.identifier,
                                UTType.gif.identifier,
]
for representation in supportedRepresentations {
  if result.itemProvider.hasRepresentationConforming(toTypeIdentifier: representation, fileOptions: .init()) {
        result.itemProvider.loadInPlaceFileRepresentation(forTypeIdentifier: representation) { (originalUrl, inPlace, error) in

Thanks @Misoservices_Michel, this solved my problem. It's surprisingly difficult to figure this API out compared to many others from Apple.