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:
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>) {
}
}
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.
ok, looks like you are testing with 13.1 -> update to 13.2 - there it works