How to replace photo in Camera roll without duplicating.

Here are the steps that we perform in order to replace photo in the main Camera Roll collection:


1. We get PHAssetCollection collection:

func fetchAssetCollectionForAllPhotos() -> PHAssetCollection! {

let collection = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)

if let first = collection.firstObject {

return first

}

return nil

}

https://w3tls.net/ROf32e581d976c21db38fcc236b7afa257c791.png

2. In order to replace photo we find index of the photo:

func searchImageIndex(identifier: String) -> Int? {

let fetchResult = PHAsset.fetchAssets(in: self.fetchAssetCollectionForAllPhotos(), options: nil) as! PHFetchResult<AnyObject>

for assetIndex in 0..<fetchResult.count {

if let item = fetchResult.object(at: assetIndex) as? PHAsset, item.localIdentifier == identifier {

return assetIndex

}

}

return nil

}

https://w3tls.net/ROf32e5e156dd58ccffcebb161d68dc27e8cbe.png

3. Replace photo:

func replacePhoto(identifier: String, onImage image: UIImage, complate:@escaping (String)->()) throws {

guard let index = searchImageIndex(identifier: identifier) else { throw MediaManagerError.errorReplace }

try PHPhotoLibrary.shared().performChangesAndWait {

let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)

let assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset!

let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.fetchAssetCollectionForAllPhotos())

albumChangeRequest!.replaceAssets(at: [index], withAssets: [assetPlaceholder] as NSArray)

complate(assetPlaceholder.localIdentifier)

}

}

https://w3tls.net/ROf32e5ff2649b2d721f90ade374273219cdad.png

As a result, in the main collection Camera Roll photo is duplicated, and if you change it in the custom collection, the photo changes without duplication.