I want to update the image in firebase storage when my State
changes. Currently I call my function to upload the picked image to storage in the onAppear
:
@State var shouldShowImagePicker: Bool = false
@State var image: UIImage?
Button(action: {
shouldShowImagePicker.toggle()
}) {
if let image = self.image {
Image(uiImage: image)
.resizable()
.frame(maxWidth: 300, maxHeight: 300)
.scaledToFit()
.onAppear() {
persistImageToStorage()
}
} else {
Text("Select Image")
.frame(width: 300, height: 300)
}
}
.fullScreenCover(isPresented: $shouldShowImagePicker, onDismiss: nil) {
ImagePicker(image: $image)
}
This is the function to upload the image to storage:
private func persistImageToStorage() {
let ref = FirebaseManager.shared.storage.reference(withPath: "image")
guard let imageData = self.image?.jpegData(compressionQuality: 0.5)
else { return }
ref.putData(imageData, metadata: nil) { metadata, err in
if let err = err {
print(err)
return
}
ref.downloadURL { url, err in
if let err = err {
print(err)
return
}
}
}
}
This is my ImagePicker
component:
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Binding var image: UIImage?
private let controller = UIImagePickerController()
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let parent: ImagePicker
init(parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
parent.image = info[.originalImage] as? UIImage
picker.dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true)
}
}
func makeUIViewController(context: Context) -> some UIViewController {
controller.delegate = context.coordinator
return controller
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
Doing it this way works fine the first time I open the ImagePicker
but once an image is selected it does not call the function again since the onAppear does not call again.
I tried setting onChange on the binding
of the image but it seemed to not work for me.
CodePudding user response:
You could create a Binding
that explicitly persists the image when the value is set
:
.fullScreenCover(isPresented: $shouldShowImagePicker, onDismiss: nil) {
let imageBinding = Binding(
get: { image },
set: { value in
image = value
persistImageToStorage()
}
)
ImagePicker(image: imageBinding)
}
Note: Since imageBinding
is already a Binding
, you do not use a $
here.
Tested in Xcode 13.4.1
You said using onChange
with image
did not work for you, but I also found this to work:
ImagePicker(image: $image)
.onChange(of: image) { _ in
persistImageToStorage()
}