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组件。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/26934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动控制理论实验---IDFT和FFT算法的原理和MATLAB编程

1、实验设备 PC计算机1台&#xff0c;MATLAB软件1套。 2、实验目的 掌握IDFT&#xff08;逆离散傅里叶变换&#xff09;算法的原理和MATLAB编程方法。了解FFT&#xff08;快速傅里叶变换&#xff09;算法&#xff0c;并能够调用MATLAB的fft函数进行频域变换。验证IDFT程序的…

数据预处理之基于统计的(3σ,Z分数,Boxplot箱线图)异常值检测#matlab

基于统计的异常值检测 1.异常值的含义 异常值是指在数据集中偏离大部分数据的数据&#xff0c;使人怀疑这些数据的偏离并非由随机因素产生&#xff0c;而是产生于完全不同的机制。 异常挖掘(outlier mining)问题由两个子问题构成&#xff1a;(1)如何度量异常。(2)如何有效发…

金融与大模型:引领行业未来的创新融合

前言 在数字化浪潮席卷全球的今天&#xff0c;金融与大模型的结合正成为行业发展的新引擎。这种融合不仅为金融机构带来了前所未有的效率和准确性&#xff0c;也为金融市场的稳定与发展注入了新的活力。本文将基于当前的市场现状&#xff0c;结合金融环境的发展&#xff0c;深…

图片查看器

目录 一 原型 二 源码 一 原型 二 源码 namespace 图片查看器 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){//默认显示第一张图片pictureBox1.Image imageList1.Images[0];}private v…

《未选择的路》

2024年&#xff0c;计算机相关专业还值得选择吗&#xff1f; 看到这个话题活动&#xff0c;回想起自己过去做的许多选择&#xff0c;思绪良久。 一首诗送给大家吧。 顾子欣 译 列位&#xff0c;共勉。

【PB案例学习笔记】-21小大写金额转换

写在前面 这是PB案例学习笔记系列文章的第21篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

ARM32开发--IIC时钟案例

知不足而奋进 望远山而前行 目录 文章目录 前言 目标 内容 需求 开发流程 移植驱动 修改I2C实现 测试功能 总结 前言 在现代嵌入式系统开发中&#xff0c;移植外设驱动并测试其功能是一项常见的任务。本次学习的目标是掌握移植方法和测试方法&#xff0c;以实现对开…

Undertow学习

Undertow介绍 Undertow是一个用java编写的灵活、高性能的web服务器&#xff0c;提供基于NIO的阻塞和非阻塞API。 Undertow有一个基于组合的体系结构&#xff0c;允许您通过组合小型单用途处理程序来构建web服务器。为您提供了在完整的Java EE servlet 4.0容器或低级别非阻塞处…

C# 设置PDF表单不可编辑、或提取PDF表单数据

PDF表单是PDF中的可编辑区域&#xff0c;允许用户填写指定信息。当表单填写完成后&#xff0c;有时候我们可能需要将其设置为不可编辑&#xff0c;以保护表单内容的完整性和可靠性。或者需要从PDF表单中提取数据以便后续处理或分析。 之前文章详细介绍过如何使用免费Spire.PDF…

PHP在线生成查询产品防伪证书系统源码

源码介绍 PHP在线生成查询产品防伪证书系统源码&#xff0c;源码自带90套授权证书模板&#xff0c;带PSD公章模板&#xff0c;证书PSD源文件。 环境要求&#xff1a;PHPMYSQL&#xff0c;PHP 版本请使用PHP5.1 ~5.3。 图片截图 源码安装说明 1.上传所有文件至你的空间服务器…

免费的端口映射工具哪个好用

端口映射&#xff0c;即从一个网络环境下的端口映射到另一个网络环境下访问的过程。通常由软件方式来提供这一过程的实现&#xff0c;或一些客户端工具。当涉及内外网时&#xff0c;如内网端口地址映射到外网地址&#xff0c;即是内网穿透的原理。免费的端口映射工具有哪些&…

PHP和Mysql前后端交互效果实现

一、连接数据库基本函数 mysqli_connect(); 作用&#xff1a;创建数据库连接&#xff0c;打开一个新的mysql的连接。传参顺序&#xff1a;数据库地址、数据库账号、数据库密码 <?phpecho mysqli_connect("localhost",root,root) ?> /*结果&#xff1a;F…

翻译《The Old New Thing》- The case of the exception that a catch (…) didn’t catch

The case of the exception that a catch (...) didnt catch - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20240405-00/?p109621 Raymond Chen 2024年04月05日 一位客户认为他们修复了一个bug&#xff0c;但他们仍然因为这个bug而崩溃。…

python django初步搭建(一)

记录一次简单的python django使用&#xff0c;后续调用api相关的暂时不想写。。。 一、环境 windows python 3.11.7 django 二、初步搭建 2.1 新建空文件夹 为了方便本次记录&#xff0c;新建了一个空的文件夹来使用。 直接在这里输入cmd 然后按下回车 2.2 安装virtual…

vue页面和 iframe多页面无刷新方案和并行存在解决方案

面临问题 : back的后台以jsp嵌套iframe为主, 所以在前端框架要把iframe无刷新嵌套和vue页面进行并行使用,vue的keep-alive只能对虚拟dom树 vtree 进行缓存无法缓存iframe,所以要对iframe进行处理 tab标签的切换效果具体参考若依框架的tab切换,可以去若依看源码,若依源码没有实…

C++设计模式——Proxy代理模式

一&#xff0c;代理模式简介 代理模式是一种 结构型设计模式&#xff0c;该模式通过引入一个新的代理对象Proxy&#xff0c;来间接访问原始对象&#xff0c;从而使访问方式变得灵活和可控。 代理对象的设定减少了客户端与真实对象之间的直接交互。 通过引入代理对象来间接访问原…

农资投入品系统架构:数字化农业的技术支撑与创新

在当今数字化时代&#xff0c;农业领域也在迅速迈向数字化和智能化的新阶段。农资投入品系统作为农业生产的重要支撑&#xff0c;其系统架构的设计与创新对于提高农业生产效率、保障粮食安全具有重要意义。本文将探讨农资投入品系统架构的设计原则、核心模块以及未来发展趋势。…

OrangePi AIpro测评:性能、应用与开发者体验解析

一、OrangePi AIpro介绍 OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/128GB/256GB eMMC模块&#xff0c;支持双4K高…

AI虚拟试穿技术:开启高保真、多场景、多样化服装组合的试穿应用

随着电子商务的快速发展,消费者对于在线购物体验的要求越来越高。特别是在服装领域,消费者渴望能够在购买前直观地了解服装的试穿效果。传统的虚拟试穿技术虽然已有一定的发展,但在不同场景下的高保真度和鲁棒性方面仍面临挑战。为此,我们研发了一种全新的AI虚拟试穿技术,…

2.spring cloud gateway 源码编译

spring cloud gateway编译 1.编译 命令 mvn clean compile -U2.报错 报错信息 核心信息 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.1.2:check (checkstyle-validation) on project spring-cloud-gateway-mvc: Failed during …