0

I got class:

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
    }

}

in which I initialized @Published var display which receives the result of the detectFlower() function that is in the function imagePickerController. In structure ScanWithCamera I'd like to use this values to set a text in Text(). I initialized in struct @EnvironmentObject var env: ImagePickerCoordinator and set Text(env.display), but I get a Fatal error: No ObservableObject of type ImagePickerCoordinator found. A View.environmentObject(_:) for ImagePickerCoordinator may be missing as an ancestor of this view.

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)
        }
    }
}

How is the way to pass this text from class function to struct?

1 Answer 1

1

Add in your SceneDelegate

let env = ImagePickerCoordinator()

And add to your rootViewController:

window.rootViewController = UIHostingController(rootView: contentView.environmentObject(env))

Now your ImagePickerCoordinator is connected to your environment.

And don't use @Binding in your Class.

Use @Published for "image" and "isShown" in your class too. You can then access all those variables by env.image for example in your ScanWithCamera-View.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.