我上课了:
class ImagePickerCoordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate, ObservableObject{
@Published var display = "Name"
@Binding var image: UIImage?
@Binding var isShown: Bool
init(image: Binding<UIImage?>, isShown: Binding<Bool>){
_image = image
_isShown = isShown
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let uiImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
guard let convertedCIImage = CIImage(image: uiImage) else {
fatalError("Cannot convert UIImage to CIIMage.")
}
detectFlower(image: convertedCIImage) { (flowerString, error) in
self.display = flowerString!
}
image = uiImage
isShown = false
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isShown = false
}
func detectFlower(image: CIImage,completion: @escaping (_ getString:String?,_ error:Error?)-> Void) {
guard let model = try? VNCoreMLModel(for: FlowerModels().model) else {
fatalError("Cannot import a model.")
}
let request = VNCoreMLRequest(model: model) { (request, error) in
let classification = request.results?.first as? VNClassificationObservation
let nameOfFlower = String(classification?.identifier ?? "Unexpected type")
completion(nameOfFlower,nil)
}
let handler = VNImageRequestHandler(ciImage: image)
do {
try handler.perform([request])
} catch {
print(error)
completion(nil,error)
}
}
}
struct ImagePicker: UIViewControllerRepresentable {
typealias UIViewControllerType = UIImagePickerController
typealias Coordinator = ImagePickerCoordinator
@Binding var image: UIImage?
@Binding var isShown: Bool
var sourceType: UIImagePickerController.SourceType = .camera
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
func makeCoordinator() ->ImagePicker.Coordinator {
return ImagePickerCoordinator(image: $image, isShown: $isShown)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = sourceType
picker.delegate = context.coordinator
return picker
}
}
在其中初始化了@Published var显示,该显示接收函数imagePickerController中的detectFlower()函数的结果。在结构ScanWithCamera中,我想使用此值在Text()中设置文本。我在struct @EnvironmentObject var env中初始化:ImagePickerCoordinator并设置了Text(env.display),但出现致命错误:没有找到ImagePickerCoordinator类型的ObservableObject。作为该视图的祖先,可能缺少用于ImagePickerCoordinator的View.environmentObject(_:)。
struct ScanWithCamera: View {
@State private var showSheet: Bool = false
@State private var showImagePicker: Bool = false
@State private var sourceType: UIImagePickerController.SourceType = .camera
@State private var userImage: UIImage?
@EnvironmentObject var env: ImagePickerCoordinator
var body: some View {
NavigationView{
VStack{
Text(env.display)
.foregroundColor(.blue)
.font(.system(size: 25))
Image(uiImage: userImage ?? UIImage(named: "flower_logo")!)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 400, height: 400)
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .top)
}
.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarItems(trailing:
HStack {
Button("Camera") {
self.showImagePicker = true
self.sourceType = .photoLibrary
print("Camera tapped!")
}
}
)
.sheet(isPresented: $showImagePicker) {
ImagePicker(image: self.$userImage, isShown: self.$showImagePicker, sourceType: self.sourceType).environmentObject(self.env)
}
}
}
如何将此文本从类函数传递到struct?
答案 0 :(得分:1)
添加您的场景代理
let env = ImagePickerCoordinator()
并添加到您的rootViewController中:
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(env))
现在您的ImagePickerCoordinator已连接到您的环境。
请勿在班级中使用@Binding
。
在类中也将@Published
用于“图像”和“ isShown”。
然后,您可以通过env.image
访问所有这些变量,例如在您的ScanWithCamera-View中。