I made a media picker for SwiftUI, but for some reason every asset I click it creates a copy of that image in the camera roll and cannot find out why. Any ideas here?
struct MediaPicker: UIViewControllerRepresentable {
@Binding var selectedAssets: [PHAsset]
func makeUIViewController(context: Context) -> PHPickerViewController {
var configuration = PHPickerConfiguration()
configuration.filter = .any(of: [.images, .videos]) // Allow both images and videos
configuration.selectionLimit = 10
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
// Update the view controller if needed
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, PHPickerViewControllerDelegate {
let parent: MediaPicker
init(_ parent: MediaPicker) {
self.parent = parent
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
for result in results {
if result.itemProvider.canLoadObject(ofClass: UIImage.self) {
result.itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in
if let image = object as? UIImage {
// Check if an asset with the same local identifier already exists
let localIdentifier = PHAsset.localIdentifier(forImage: image)
if let existingAsset = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil).firstObject {
DispatchQueue.main.async {
self.parent.selectedAssets.append(existingAsset)
}
} else {
// Convert UIImage to PHAsset
PHAsset.imageAsset(image: image) { asset in
if let asset = asset {
DispatchQueue.main.async {
self.parent.selectedAssets.append(asset)
}
} else {
// Handle error
}
}
}
}
}
}
}
picker.dismiss(animated: true, completion: nil)
}
}
}
extension PHAsset {
static func imageAsset(image: UIImage, completion: @escaping (PHAsset?) -> Void) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let request = PHAssetChangeRequest.creationRequestForAsset(from: image)
placeholder = request.placeholderForCreatedAsset
}, completionHandler: { success, error in
if success, let placeholder = placeholder,
let asset = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil).firstObject {
// Asset creation was successful
completion(asset)
} else {
// Handle error
completion(nil)
}
})
}
}
extension PHAsset {
static func localIdentifier(forImage image: UIImage) -> String {
// Generate a unique local identifier based on the image data.
guard let imageData = image.jpegData(compressionQuality: 1.0) else {
return ""
}
let hash = imageData.hashValue
return "\(hash)"
}
}