SwiftUI UIViewRepresentable and Custom Delegate

人盡茶涼 提交于 2021-01-29 06:34:04

问题


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'


回答1:


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
}


来源:https://stackoverflow.com/questions/59077774/swiftui-uiviewrepresentable-and-custom-delegate

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!