2

When creating a UIViewControllerRepresentable for SwiftUI, how do you create a Coordinator so that it can access the delegate of a third party library?

In this case, I am trying to access BBMetal, a photo-filtering library.

This is a truncated version of the code we are trying to 'bridge' to SwiftUI:

class CameraPhotoFilterVC: UIViewController {
    private var camera: BBMetalCamera!
    private var metalView: BBMetalView!
    private var faceView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        camera.start()
    }...
}

extension CameraPhotoFilterVC: BBMetalCameraPhotoDelegate {
    func camera(_ camera: BBMetalCamera, didOutput texture: MTLTexture) {
        // do something with the photo
    }

    func camera(_ camera: BBMetalCamera, didFail error: Error) {
        // In main thread
        print("Fail taking photo. Error: \(error)")
    }
}

Using UIViewRepresentable everything sets up properly and the CameraPhotoFilterVC works, starts up the camera, etc, but the extension does not respond. We tried to set this up as a Coordinator:

func makeCoordinator() -> Coordinator {
 Coordinator(self)
}

func makeUIViewController(context: UIViewControllerRepresentableContext<CameraPreviewView>) -> CameraViewController {
 let cameraViewController = CameraViewController()
 // Throws an error because what we really want is a BBMetalCameraPhotoDelegate
 //cameraViewController.delegate = context.coordinator
 return cameraViewController
}

class Coordinator: NSObject, BBMetalCameraPhotoDelegate {
 var parent: CameraPreviewView
 init(_ parent: CameraPreviewView) {
  self.parent = parent
 }

 func camera(_ camera: BBMetalCamera, didOutput texture: MTLTexture) {
  print("do something with the photo")
 }
 func camera(_ camera: BBMetalCamera, didFail error: Error) {
  print("Fail taking photo. Error: \(error)")
 }
}

We also tried simply leaving an extension of the ViewController:

final class CameraViewController : UIViewController  {
...
}

extension CameraViewController: BBMetalCameraPhotoDelegate {
   func camera(_ camera: BBMetalCamera, didOutput texture: MTLTexture) {
        ...
}

However the delegate methods from BBMetalCameraPhotoDelegate do not 'fire.

I suppose the question is: in UIViewControllerRepresentable or UIViewRepresentable, how do you add an "external" delegate in the makeUIViewController method?

Usually, if this was say a UIPickerView, the following line would work:

picker.delegate = context.coordinator

But in this case the delegate is 'once removed'

2
  • 1
    Why not set camera.delegate = self in viewDidLoad? Commented Nov 27, 2019 at 20:41
  • Wow thank you for your answer. It wasn't exactly the issue but it triggered a thought on what to examine. In this case, the issue is that the third party library doesn't CALL it a delegate - it's called photoDelegate. And so all of the attempts I made would return errors. By adding camera.photoDelegate = self in viewDidLoad it worked! Thank you. Commented Nov 27, 2019 at 20:57

1 Answer 1

2

You need to set the BBMetalCamera's delegate at some point before you use it.

You might do it immediately after creating it. You didn't show how you create it, so I don't know if that would be a good place to set it.

You could probably just do it in viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()

    camera.photoDelegate = self
}
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.