JuValencia
JuValencia

Reputation: 312

Saving a photo in a custom album fails when run for the first time

Hi I am creating a photo album app as a learning project and I am having some issues with the PHPhotoLibrary.shared().performChangesAndWait; the main issue is that when the method saveImage which has the PHPhotoLibrary.shared().performChangesAndWait code; the method exits before PHPhotoLibrary.shared().performChangesAndWait finishes saving the image. It seems that code gets execute asynchronously even when I am using the performChangesAndWait method which according to the documentation says it should wait until it finishes.

Here is the code of the saveImage method in my class:

func saveImage(_ image: UIImage) ->Bool {
    print("Executing saveImage")
    var result:Bool = false
    if assetCollection == nil {
        print("the album is nil")
        return result
    }
    print("saveImage: we will start saving the image")
    //TODO: the return false is happening before the photo is save.
    do
    {
        try PHPhotoLibrary.shared().performChangesAndWait({
            let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
            let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset
            let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
            let enumeration: NSArray = [assetPlaceHolder!]
            albumChangeRequest!.addAssets(enumeration)
            print("saveImage: image was save without issues")
            result = true
            print("saveImage: result value after saving the image: \(result)")
        })
    }
    catch let error
    {
        result = false
        print("saveImage: there was a problem: \(error.localizedDescription)")
    }


    print("saveImage: result value before exiting the method: \(result)")
    return result

}

Basically again when the app runs for the first time the return result gets execute before the saving the image block finishes.

Is there any way that I can force the saveImage method to actually wait until the performChangesAndWait method actually finishes?

Thanks in advance for your help.

Upvotes: 3

Views: 1708

Answers (2)

nitin.agam
nitin.agam

Reputation: 2142

Here is the solution (Swift 5):

@objc private func handleSavePhoto() {

    guard let previewImage = self.photoImageView.image else { return }

    PHPhotoLibrary.requestAuthorization { (status) in
        if status == .authorized {
            do {
                try PHPhotoLibrary.shared().performChangesAndWait {
                    PHAssetChangeRequest.creationRequestForAsset(from: previewImage)
                }
            } catch let error {
                print("failed to save photo in library: ", error)
            }
        } else {
            print("Something went wrong with permission...")
        }
    }
}

Upvotes: 0

x4h1d
x4h1d

Reputation: 6092

performChangesAndWait is an async callback method. The changes made on result inside performChangesAndWait will not be reflected on return , as those two are in different threads.

One way to wait for saveImage method to finish is, implementing callback. Something like:

func saveImage(_ image: UIImage, callback: @escaping(_ result: Bool)->Void) {
    print("Executing saveImage")

    if assetCollection == nil {
        print("the album is nil")
        callback(false)
    }
    print("saveImage: we will start saving the image")
    //TODO: the return false is happening before the photo is save.
    do {
        try PHPhotoLibrary.shared().performChangesAndWait({
            let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
            let assetPlaceHolder = assetChangeRequest.placeholderForCreatedAsset
            let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
            let enumeration: NSArray = [assetPlaceHolder!]
            albumChangeRequest!.addAssets(enumeration)
            print("saveImage: image was save without issues")

            callback(true)
        })
    }
    catch let error {
        print("saveImage: there was a problem: \(error.localizedDescription)")
        callback(false)
    }
}

Let us know what you got.

Upvotes: 4

Related Questions