Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ImagePicker in SwiftUI

I'm trying to create an Image Picker in SwiftUI following this tutorial. Basically, the idea is that when the user taps on a grey rectangle on the screen, an image picker comes up. When they select an image, it is imported into the grey rectangle.

The problem is that, when I run the code, I get the following error: Thread 1: Fatal error: Reading Environment<Binding<PresentationMode>> outside View.body

This appears on the line parent.presentationMode.wrappedValue.dismiss() in the Image Picker Struct.

My code looks like this:

Image Picker


struct ImagePicker: UIViewControllerRepresentable {
    
  @Environment(\.presentationMode) var presentationMode
  @Binding var image: UIImage?
    
    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePicker

        init(_ parent: ImagePicker) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let uiImage = info[.originalImage] as? UIImage {
                parent.image = uiImage
            }

        parent.presentationMode.wrappedValue.dismiss()
        }     
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    

    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
   
    }
}

Content View

import SwiftUI

struct ContentView: View {
    
    @State private var image: Image?
    @State private var showingImagePicker = false
    @State private var inputImage: UIImage?
    

    var body: some View {
     NavigationView {
             ZStack {
                 Rectangle()
                     .fill(Color.secondary)

                 if image != nil {
                     image?
                         .resizable()
                         .scaledToFit()
                 } else {
                     Text("Tap to select a picture")
                 }
             }
             .onTapGesture {
                 self.showingImagePicker = true
             }


        .sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
            ImagePicker(image: self.$inputImage)
        }
     }
    }

    func loadImage() {
        guard let inputImage = inputImage else { return }
        image = Image(uiImage: inputImage)
    }
    
}

Similar to the solution recommended here, I tried replacing @Environment(\.presentationMode) var presentationMode with @Binding var isPresented: Bool in the Image Picker Struct and replacing the troublesome line parent.presentationMode.wrappedValue.dismiss() with parent.isPresented = false.

However, this caused a different problem - the image didn't load when the Sheet was dismissed (I guess because I wasn't calling the dismiss() method anywhere).

I'm pretty new to Swift and coding, so apologies if I could have been more succinct in my explanation anywhere and feel free to make corrections.

like image 791
FPL Avatar asked Mar 21 '26 15:03

FPL


1 Answers

ok, looks like you are testing with 13.1 -> update to 13.2 - there it works

like image 185
Chris Avatar answered Mar 23 '26 04:03

Chris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!