欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > SwiftUI中UIViewRepresentable的使用(UIKit与SwiftUI的桥梁)

SwiftUI中UIViewRepresentable的使用(UIKit与SwiftUI的桥梁)

2024/10/24 20:12:41 来源:https://blog.csdn.net/guoyongming925/article/details/139654246  浏览:    关键词:SwiftUI中UIViewRepresentable的使用(UIKit与SwiftUI的桥梁)

UIViewRepresentable是一个协议,用于创建一个SwiftUI视图,该视图包装了一个UIKit视图。通过实现UIViewRepresentable协议,我们可以在SwiftUI中使用自定义的UIKit视图,并与SwiftUI进行交互。

实现UIViewRepresentable

创建一个遵循UIViewRepresentable协议的自定义结构体,比如我们用TextField举例,创建一个TextFieldViewRepresentable,并实现该协议最基础的两个协议方法。

  • makeUIView(context:):创建并返回UIKit视图。
  • updateUIView(_:context:):更新UIKit视图。
struct TextFieldViewRepresentable: UIViewRepresentable {func makeUIView(context: Context) -> some UIView {let textField = UITextField()return textField}func updateUIView(_ uiView: UIViewType, context: Context) {}
}

如果在makeUIView方法中明确了要返回的UIKit控件的类型,那么方法的返回值就可以改为指定的类型,而不是some UIView,改完后,把updateUIView方法删了,再重新添加,就会发现updateUIView方法中的uiView的类型不是UIViewType了,而是我们在makeUIView方法中的返回类型。

struct TextFieldViewRepresentable: UIViewRepresentable {func makeUIView(context: Context) -> UITextField {let textField = UITextField()textField.backgroundColor = UIColor.grayreturn textField}func updateUIView(_ uiView: UITextField, context: Context) {}
}

SwiftUI中调用:

struct UIViewRepresentableDemo: View {var body: some View {VStack {Text("Hello, World!")TextFieldViewRepresentable()}}
}

UIKit向SwiftUI传值

上面的代码中,我们在TextField中输入任何内容都不会显示在SwiftUI的界面上的,也就是SwiftUI拿不到TextField中输入的内容,这里我们就需要绑定一个值来传递了。

要想拿到输入的内容,我们组要一个协调员去处理TextFieldDelegate的方法,这里就需要实现makeCoordinator()方法。makeCoordinator()方法也是UIViewRepresentable的协议方法。下面在TextFieldViewRepresentable结构体里面定义一个协调员Coordinator

struct TextFieldViewRepresentable: UIViewRepresentable {@Binding var text: Stringfunc makeUIView(context: Context) -> UITextField {let textField = UITextField()textField.backgroundColor = UIColor.graytextField.delegate = context.coordinatorreturn textField}func makeCoordinator() -> Coordinator {return Coordinator(text: $text)}class Coordinator: NSObject, UITextFieldDelegate {@Binding var text: Stringinit(text: Binding<String>) {self._text = text}func textFieldDidChangeSelection(_ textField: UITextField) {text = textField.text ?? ""}}
}

上面代码中我们创建一个类Coordinator,注意是class类型,该类实现了UITextFieldDelegate协议。

Coordinator类中定义了一个@Binding修饰的text属性,用于绑定输入的值。在textFieldDidChangeSelection协议方法中进行赋值。

TextFieldViewRepresentable中我们也定义了一个@Binding修饰的text属性,用于绑定SwiftUI中的@State修饰的String类型的值。

在实现的makeCoordinator()方法中,创建并返回Coordinator的具体实例,并绑定text

makeUIView方法中,这里我们通过contextcoordinator属性能拿到刚才通过makeCoordinator()方法创建的Coordinator实例,并将UITextField的代理设置为该实例。

textField.delegate = context.coordinator

SwiftUI部分调用代码:

struct UIViewRepresentableDemo: View {@State private var text: String = ""var body: some View {VStack {Text(text)TextFieldViewRepresentable(text: $text).frame(height: 50).padding()}}
}

使用效果如下,在输入框输入的时候,界面显示出了输入的内容。
在这里插入图片描述

SwiftUI向UIKit传值

有些时候SwiftUI界面不断刷新的时候,也需要想UIKit组件传递数据,比如刚才的代码,修改一下增加了一个SwiftUITextField组件。
在这里插入图片描述
UIKitTextField输入的时候,SwiftUITextField也显示了输入的字符串,因为我们已经将text值传到SwiftUI界面了。
但是当SwiftUITextField在输入的时候,UIKitTextField确没有任何显示。要实现这个,我们需要用到前面提到的updateUIView方法了,该方法在SwiftUI界面刷新的时候调用。

func updateUIView(_ uiView: UITextField, context: Context) {uiView.text = text
}

text是通过@Binding绑定的值,我们将这个textUITextField即可。

定义修饰符方法

TextFieldViewRepresentable是我们定义的一个用在SwiftUI中的结构体,我们给它加一些方法,这样在SwiftUI中通过点语法就可以修改TextFieldViewRepresentable的某些属性了。

TextFieldViewRepresentable组件可能用在很多地方,不同的用处可能会设置不同的样式属性等,比如说背景色,如果在SwiftUI中直接调用.background(Color.red)方法,是不起作用的,因为没有直接修改到UITextField

在这里插入图片描述
那么现在在TextFieldViewRepresentable中添加一个属性和一个方法。

var backgroundColor: UIColor?
func backgroundColor(_ color: UIColor) -> TextFieldViewRepresentable {var clone = selfclone.backgroundColor = colorreturn clone
}

该方法传入UIColor,并返回TextFieldViewRepresentable实例,即当前的self,这样在SwiftUI中就可以连续调用点语法了。

makeUIView方法中,我们给UITextField设置backgroundColor

func makeUIView(context: Context) -> UITextField {let textField = UITextField()textField.delegate = context.coordinatortextField.placeholder = "Please input..."textField.borderStyle = .roundedRecttextField.backgroundColor = backgroundColorreturn textField
}

最终调用和效果如下:
在这里插入图片描述
切记自定义的方法要在SwiftUI中初始化组件后就调用,如果在系统的修饰符方法后调用则会报错的,因为其他修饰符方法返回的是some View类型,该类型下是没有我们定义的方法的。

完整代码

struct UIViewRepresentableDemo: View {@State private var text: String = ""var body: some View {VStack {Text(text)HStack {Text("SwiftUI:")TextField("Please input...", text: $text).textFieldStyle(.roundedBorder)}HStack {Text("UIKit:")TextFieldViewRepresentable(text: $text).backgroundColor(UIColor.cyan).frame(height: 50).padding()}}}
}struct TextFieldViewRepresentable: UIViewRepresentable {@Binding var text: Stringvar backgroundColor: UIColor?func makeUIView(context: Context) -> UITextField {let textField = UITextField()textField.delegate = context.coordinatortextField.placeholder = "Please input..."textField.borderStyle = .roundedRecttextField.backgroundColor = backgroundColorreturn textField}func updateUIView(_ uiView: UITextField, context: Context) {uiView.text = text}func backgroundColor(_ color: UIColor) -> TextFieldViewRepresentable {var clone = selfclone.backgroundColor = colorreturn clone}func makeCoordinator() -> Coordinator {return Coordinator(text: $text)}class Coordinator: NSObject, UITextFieldDelegate {@Binding var text: Stringinit(text: Binding<String>) {self._text = text}func textFieldDidChangeSelection(_ textField: UITextField) {text = textField.text ?? ""}}
}

写在最后

本文主要介绍了在SwiftUI中如何包装UIKit组件,当SwiftUI组件无法满足我们的App设计需求的时候,可以使用UIKit组件。

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com