SwiftUI 中的图片选择器
ImagePicker in SwiftUI
我正在尝试在 this tutorial 之后的 SwiftUI 中创建图像选择器。基本上,这个想法是当用户点击屏幕上的灰色矩形时,会出现一个图像选择器。当他们 select 一个图像时,它被导入到灰色矩形中。
问题是,当我 运行 代码时,出现以下错误:
Thread 1: Fatal error: Reading Environment<Binding<PresentationMode>> outside View.body
这出现在图像选择器结构中的 parent.presentationMode.wrappedValue.dismiss()
行。
我的代码如下所示:
图像选择器
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)
}
}
与推荐的解决方案here类似,我尝试在Image Picker Struct中将@Environment(\.presentationMode) var presentationMode
替换为@Binding var isPresented: Bool
并将麻烦的行parent.presentationMode.wrappedValue.dismiss()
替换为parent.isPresented = false
.
然而,这导致了另一个问题 - 当 Sheet 被关闭时图像没有加载(我猜是因为我没有在任何地方调用 dismiss()
方法)。
我对 Swift 和编码还很陌生,所以很抱歉,如果我可以在任何地方更简洁地解释并随时进行更正。
好的,看来您正在使用 13.1 进行测试 -> 更新到 13.2 - 它可以正常工作
我正在尝试在 this tutorial 之后的 SwiftUI 中创建图像选择器。基本上,这个想法是当用户点击屏幕上的灰色矩形时,会出现一个图像选择器。当他们 select 一个图像时,它被导入到灰色矩形中。
问题是,当我 运行 代码时,出现以下错误:
Thread 1: Fatal error: Reading Environment<Binding<PresentationMode>> outside View.body
这出现在图像选择器结构中的 parent.presentationMode.wrappedValue.dismiss()
行。
我的代码如下所示:
图像选择器
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)
}
}
与推荐的解决方案here类似,我尝试在Image Picker Struct中将@Environment(\.presentationMode) var presentationMode
替换为@Binding var isPresented: Bool
并将麻烦的行parent.presentationMode.wrappedValue.dismiss()
替换为parent.isPresented = false
.
然而,这导致了另一个问题 - 当 Sheet 被关闭时图像没有加载(我猜是因为我没有在任何地方调用 dismiss()
方法)。
我对 Swift 和编码还很陌生,所以很抱歉,如果我可以在任何地方更简洁地解释并随时进行更正。
好的,看来您正在使用 13.1 进行测试 -> 更新到 13.2 - 它可以正常工作