ios - 如何在包装器 Swift View 中使用自定义 UIView 的扩展功能?
问题描述
(在 Xcode 11.3、Swift 5.1.3 中测试)
我想扩展 UIView,用 UIViewRepresentable 包装它,并将其用作 Swift View。但是,我很难从包装器 Swift View 访问自定义 UIView 的扩展功能。
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 的任何成员。
如何从 UIViewRepresentable 包装器访问我的 UIView 子类中的扩展自定义函数 startCameraCapture()?或者,是否有任何无状态、体面的解决方案可以在 SwiftUI 中使用扩展的旧 UIView?
解决方案
你应该创建一个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)
}
}
推荐阅读
- javascript - 如何在反应 js 或 javascript 中从 html 生成图像?
- css - Css :not 伪类没有生效
- java - 如何在 Java Spring 中执行预构建查询
- python - 使用 lambda 和 getattr 循环制作按钮
- php - 如何从这个 json 响应中得到一个准确的值?
- flutter - 存储数据,以便在 Flutter 中全局可用
- c++ - gcc中的二义运算符
- java - 方法不会在 JUnit5 测试用例中抛出
- database - Liquibase tag rollback command
- android - Cordova 应用程序突然没有互联网连接;似乎没有什么可以解决的