Reputation: 312
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
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
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