skip to Main Content

Users can download image and video files from a server which are then stored temporarily under the app’s Documents path and then copied from there to a custom album in the iOS photo library with either PHAssetChangeRequest.creationRequestForAssetFromImage or PHAssetChangeRequest.creationRequestForAssetFromVideo.

This works flawless when only image files OR video files are downloaded but when both images and videos are mixed in the same download batch there are always some files failing arbitrarily with one of these errors:

Error was: The operation couldn’t be completed. (PHPhotosErrorDomain error -1.)

or

Error was: The operation couldn’t be completed. (PHPhotosErrorDomain error 3302.)

This is the responsible code for copying files to the photo library:

public func saveFileToPhotoLibrary(_ url: URL, completion: @escaping (Bool) -> Void)
{
    guard let album = _album else
    {
        completion(false)
        return
    }

    guard let supertype = url.supertype else
    {
        completion(false)
        return
    }

    if supertype == .image || supertype == .movie
    {
        DispatchQueue.global(qos: .background).async
        {
            PHPhotoLibrary.shared().performChanges(
            {
                guard let assetChangeRequest = supertype == .image
                    ? PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: url)
                    : PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url) else
                {
                    completion(false)
                    return
                }

                guard let assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset else
                {
                    completion(false)
                    return
                }

                guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album) else
                {
                    completion(false)
                    return
                }

                albumChangeRequest.addAssets([assetPlaceholder] as NSFastEnumeration)
            })
            {
                saved, error in

                if let error = error
                {
                    print("Failed to save image file from (url.lastPathComponent) to photo gallery. Error was: (error.localizedDescription)")
                    DispatchQueue.main.async { completion(false) }
                }
            }
        }
    }
}

Does anyone know why the errors happen or how to solve this issue so that no file copies are failing?

2

Answers


  1. Chosen as BEST ANSWER

    Solved it! The above code works as intended. The problem was that file types were mixed up between some video and image files due to file order and filenames provided from server. So sometimes a video might have received an image file type extension and vice versa. This seems to confuse the PHPhotoLibrary creationRequestForAssetFromImage API.


  2. PHPhotosErrorDomain error 3302 means invalidResource, see list of error codes. This happened to me because I tried to save a picture from a file in the temporary directory. It seems only specific directories can be used:

    // FAILS
    let imageUrl = FileManager.default.temporaryDirectory.appendingPathComponent("save-me")
    
    // WORKS
    let documentsPath = NSSearchPathForDirectoriesInDomains(
      .documentDirectory, .userDomainMask, true)[0]
    let filePath = "(documentsPath)/tempFile.jpg"
    let imageUrl = URL(fileURLWithPath: filePath)
    
    // And then
    PHPhotoLibrary.shared().performChanges(
      {
        let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(
          atFileURL: imageUrl)
    
        [...]
    

    You can also get other cryptic errors. For instance, 3300 means changeNotSupported and can occur if you try to add an asset to special albums such as "Recents" (which identifies as PHAssetCollectionType.smartAlbum + PHAssetCollectionSubtype.smartAlbumUserLibrary).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search