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

2024-06-14 07:44

本文主要是介绍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组件。

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

这篇关于SwiftUI中UIViewRepresentable的使用(UIKit与SwiftUI的桥梁)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1059794

相关文章

Spring Cloud之注册中心Nacos的使用详解

《SpringCloud之注册中心Nacos的使用详解》本文介绍SpringCloudAlibaba中的Nacos组件,对比了Nacos与Eureka的区别,展示了如何在项目中引入SpringClo... 目录Naacos服务注册/服务发现引⼊Spring Cloud Alibaba依赖引入Naco编程s依

Java springBoot初步使用websocket的代码示例

《JavaspringBoot初步使用websocket的代码示例》:本文主要介绍JavaspringBoot初步使用websocket的相关资料,WebSocket是一种实现实时双向通信的协... 目录一、什么是websocket二、依赖坐标地址1.springBoot父级依赖2.springBoot依赖

Java使用Mail构建邮件功能的完整指南

《Java使用Mail构建邮件功能的完整指南》JavaMailAPI是一个功能强大的工具,它可以帮助开发者轻松实现邮件的发送与接收功能,本文将介绍如何使用JavaMail发送和接收邮件,希望对大家有所... 目录1、简述2、主要特点3、发送样例3.1 发送纯文本邮件3.2 发送 html 邮件3.3 发送带

使用DeepSeek搭建个人知识库(在笔记本电脑上)

《使用DeepSeek搭建个人知识库(在笔记本电脑上)》本文介绍了如何在笔记本电脑上使用DeepSeek和开源工具搭建个人知识库,通过安装DeepSeek和RAGFlow,并使用CherryStudi... 目录部署环境软件清单安装DeepSeek安装Cherry Studio安装RAGFlow设置知识库总

Python FastAPI入门安装使用

《PythonFastAPI入门安装使用》FastAPI是一个现代、快速的PythonWeb框架,用于构建API,它基于Python3.6+的类型提示特性,使得代码更加简洁且易于绶护,这篇文章主要介... 目录第一节:FastAPI入门一、FastAPI框架介绍什么是ASGI服务(WSGI)二、FastAP

Spring-AOP-ProceedingJoinPoint的使用详解

《Spring-AOP-ProceedingJoinPoint的使用详解》:本文主要介绍Spring-AOP-ProceedingJoinPoint的使用方式,具有很好的参考价值,希望对大家有所帮... 目录ProceedingJoinPoijsnt简介获取环绕通知方法的相关信息1.proceed()2.g

Maven pom.xml文件中build,plugin标签的使用小结

《Mavenpom.xml文件中build,plugin标签的使用小结》本文主要介绍了Mavenpom.xml文件中build,plugin标签的使用小结,文中通过示例代码介绍的非常详细,对大家的学... 目录<build> 标签Plugins插件<build> 标签<build> 标签是 pom.XML

JAVA虚拟机中 -D, -X, -XX ,-server参数使用

《JAVA虚拟机中-D,-X,-XX,-server参数使用》本文主要介绍了JAVA虚拟机中-D,-X,-XX,-server参数使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录一、-D参数二、-X参数三、-XX参数总结:在Java开发过程中,对Java虚拟机(JVM)的启动参数进

Java中使用注解校验手机号格式的详细指南

《Java中使用注解校验手机号格式的详细指南》在现代的Web应用开发中,数据校验是一个非常重要的环节,本文将详细介绍如何在Java中使用注解对手机号格式进行校验,感兴趣的小伙伴可以了解下... 目录1. 引言2. 数据校验的重要性3. Java中的数据校验框架4. 使用注解校验手机号格式4.1 @NotBl

Python使用DeepSeek进行联网搜索功能详解

《Python使用DeepSeek进行联网搜索功能详解》Python作为一种非常流行的编程语言,结合DeepSeek这一高性能的深度学习工具包,可以方便地处理各种深度学习任务,本文将介绍一下如何使用P... 目录一、环境准备与依赖安装二、DeepSeek简介三、联网搜索与数据集准备四、实践示例:图像分类1.