简体   繁体   English

SwiftUI UIViewRepresentable 和自定义委托

[英]SwiftUI UIViewRepresentable and Custom Delegate

When creating a UIViewControllerRepresentable for SwiftUI, how do you create a Coordinator so that it can access the delegate of a third party library?在为 SwiftUI 创建 UIViewControllerRepresentable 时,如何创建 Coordinator 以便它可以访问第三方库的委托?

In this case, I am trying to access BBMetal , a photo-filtering library.在这种情况下,我试图访问BBMetal ,一个照片过滤库。

This is a truncated version of the code we are trying to 'bridge' to SwiftUI:这是我们试图“桥接”到 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.使用 UIViewRepresentable 一切设置正确,CameraPhotoFilterVC 工作,启动相机等,但扩展没有响应。 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:我们还尝试简单地留下 ViewController 的扩展:

final class CameraViewController : UIViewController  {
...
}

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

However the delegate methods from BBMetalCameraPhotoDelegate do not 'fire.然而,来自 BBMetalCameraPhotoDelegate 的委托方法不会“触发”。

I suppose the question is: in UIViewControllerRepresentable or UIViewRepresentable, how do you add an "external" delegate in the makeUIViewController method?我想问题是:在 UIViewControllerRepresentable 或 UIViewRepresentable 中,如何在 makeUIViewController 方法中添加“外部”委托?

Usually, if this was say a UIPickerView, the following line would work:通常,如果这是一个 UIPickerView,下面这行会起作用:

picker.delegate = context.coordinator

But in this case the delegate is 'once removed'但在这种情况下,代表“一旦被移除”

You need to set the BBMetalCamera 's delegate at some point before you use it.在使用之前,您需要在某个时候设置BBMetalCamera的委托。

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 :您可能只在viewDidLoad执行此操作:

override func viewDidLoad() {
    super.viewDidLoad()

    camera.photoDelegate = self
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM