SwiftUI Image Pick is creating Camera Roll Copies

24 Views Asked by At

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)"
    }
}
0

There are 0 best solutions below