Как использовать расширенную функцию пользовательского UIView в оболочке Swift View? - PullRequest
0 голосов
/ 15 января 2020

(протестировано в Xcode 11.3, Swift 5.1.3)

Я хочу расширить UIView, обернуть его UIViewRepresentable и использовать в качестве Swift View. Однако мне трудно получить доступ к расширенным функциям пользовательского UIView из оболочки Swift View.

class UICameraCaptureImageView: UIImageView, AVCaptureVideoDataOutputSampleBufferDelegate {
  @State var capturedImage: UIImage? = UIImage(named: "default_placeholder")

  func startCameraCapture()  {  
    // start camera capture when it is ready
  }

  // AVCaptureVideoDataOutputSampleBufferDelegate delegate method follows
  // ...

}
struct CameraCaptureImageView: UIViewRepresentable {

  // cannot set containedUIView in makeUIView/updateUIView, and they are not mutating method
  private var containedUIView: UICameraCaptureImageView?

  func makeUIView(context: UIViewRepresentableContext<CameraCaptureImageView>) -> 
      UICapturedImageView {
    UICapturedImageView()     
  }

  func updateUIView(_ uiView: UICapturedImageView, 
      context: UIViewRepresentableContext< CameraCaptureImageView>) {
    uiView.image = capturedImage
  }

  func startCameraCapture()  {  
    // redirect to UICameraCaptureImageView.startCameraCapture(), 
    // but cannot set self.containedUIView
    guard self.containedUIView != nil else {
      print("The containedUICaptureView doesn't exist")
      return
    }
    self.containedUIView?.startCameraCapture()
  }
}

Сначала, хотя это своего рода стратегия с сохранением состояния, я попытался объявить переменную-член в CameraCaptureImageView и установить экземпляр UICameraCaptureImageView, когда он будет создан. Но, как вы видите, makeUIView () не объявлен как метод мутирования, поэтому я не могу изменять любые члены CameraCaptureImageView.

Как получить доступ к расширенной пользовательской функции startCameraCapture () в моем подклассе UIView из оболочки UIViewRepresentable? Или есть ли какое-либо достойное решение без сохранения состояния для использования расширенного старого UIView в SwiftUI?

1 Ответ

1 голос
/ 15 января 2020

Вы должны создать Coordinator, который управляет этим шаттлом для вас. Это class и, следовательно, не является строго обязательным для неизменяемой семантики.

struct CameraCaptureImageView: UIViewRepresentable {

  func makeUIView(context: UIViewRepresentableContext<CameraCaptureImageView>) -> 
      UICapturedImageView {
    return UICapturedImageView()     
  }

  func makeCoordinator() -> Coordinator {
    return .init(self)
  }
}

extension CameraCaptureImageView {

  // add any delegate/protocol conformances here, it's just an object!
  private class Coordinator  {
    let cameraCaptureImageView: CameraCaptureImageView

    init(_ cameraCaptureImageView: CameraCaptureImageView) {
       // CameraCaptureImageView is a `struct`, so it's a copy!
       self.cameraCaptureImageView = cameraCaptureImageView
    }

    // now here is all your UIView specific logic
  }
}

Нужен сигнал? Добавьте закрытие на View, которое Coordinator может вызывать для определенных событий.

struct CameraCaptureImageView: ... {

    let onSomeEvent: (Event) -> Void
}

class Coordinator {

    let cameraCaptureImageView: ...

    func view(_ view: UIViewOfSomeKind, didReceive event: Event) {
      cameraCaptureImageView.onEvent(event)
    }
}
...