2

I followed this tutorial and was able to successfully upload an image to my Firebase Storage.

The problem though is it uploads the picture even if you tap on it once. There's no confirmation opportunity presented to the user, which I believe is not good UX.

Here's the entire struct

struct imagePicker : UIViewControllerRepresentable{
    
    func makeCoordinator() -> imagePicker.Coordinator {
        return imagePicker.Coordinator(parent1: self)
    }
    
    @Binding var shown : Bool
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<imagePicker>) ->
        UIImagePickerController {
            
        let imagepic = UIImagePickerController()
        imagepic.sourceType = .photoLibrary
        imagepic.delegate = context.coordinator
            
        return imagepic
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<imagePicker>) {
        
    }
    
    class Coordinator : NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

        var parent : imagePicker!
        
        init(parent1: imagePicker ){
            parent = parent1
        }
        
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            parent.shown.toggle()
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            
            let image = info[.originalImage] as! UIImage
        
            let storage = Storage.storage()
            let storingimage = storage.reference().child("temp.jpg")
            
            let metadata = StorageMetadata()
            metadata.contentType = "image/jpeg"
            
            storingimage.putData(image.jpegData(compressionQuality: 0.35)!, metadata: metadata)
            {(response,err) in
                if(err != nil){
                    print(err?.localizedDescription)
                }
                else{
                    // You can also access to download URL after upload.
                    storingimage.downloadURL { (url, error) in
                      guard let downloadURL = url else {
                        // Uh-oh, an error occurred!
                        
                        return
                      }
                        // upload to
                       // I plan on storing this URL downloadURL
                    }
                }
            }
        }
    }
}

Here's a snippet of my content view

@State var showCaptureImageView = false

...

VStack{
     Button(action: {
         self.showCaptureImageView.toggle()
     }) {
         Text("Choose Photo")
     }

     if(self.$showCaptureImageView){
         imagePicker(shown: self.$showCaptureImageView)
     
         Spacer()

         Button(action: {
             // perform imageUpload here
         }, label: {
             Text("Upload Photo")
         })
     }
}

I do not know how to create the preview because imagePicker works in UIImage in this context, which I do not think can present itself as Image very intuitively.

markusp
  • 329
  • 1
  • 2
  • 10
  • 1
    very intuitively `Image(uiImage: _your_image_here)`. See for example https://stackoverflow.com/questions/58325527/photos-from-image-picker-uiimagepickercontroller-taken-in-portrait-mode-show-u – Asperi Aug 05 '20 at 03:30
  • @Asperi yes, I was missing the `image` parameter within `func makeCoordinator() -> imagePicker.Coordinator`. I'm going to write an answer – markusp Aug 05 '20 at 03:47

1 Answers1

0

I picked up some tips here. Basically, I needed to modify my makeCoordinator() by adding an image variable.

struct imagePicker {
    @Binding var shown: Bool
    @Binding var image: Image?

    func makeCoordinator() -> imagePicker.Coordinator {
        return imagePicker.Coordinator(parent1: self, image: $image)
    }

}

in the contentView, I can now read the returned value

Snippet from my VStack

if self.image != nil{
    self.image?.resizable()
    .frame(width: 250)
    .shadow(radius: 10)
    
}
if(self.showCaptureImageView){
    imagePicker(shown: self.$showCaptureImageView, image: self.$image)
}

and right below the struct

@State var showCaptureImageView = false
@State var image: Image? = nil

Now, the user can see their selected photo in a preview.

markusp
  • 329
  • 1
  • 2
  • 10