如何在包装器 Swift View 中使用自定义 UIView 的扩展功能?
Posted
技术标签:
【中文标题】如何在包装器 Swift View 中使用自定义 UIView 的扩展功能?【英文标题】:How to use extended function of the custom UIView in a wrapper Swift View? 【发布时间】:2020-01-15 06:06:55 【问题描述】:(在 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?
【问题讨论】:
【参考方案1】:你应该创建一个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)
【讨论】:
谢谢。我创建了一个协调器来符合 AVCaptureVideoDataOutputSampleBufferDelegate 并解决了问题。 :)以上是关于如何在包装器 Swift View 中使用自定义 UIView 的扩展功能?的主要内容,如果未能解决你的问题,请参考以下文章