大家好,我的开源项目PakePlus可以将网页/Vue/React项目打包为桌面/手机应用并且小于5M只需几分钟,官网地址:pakeplus.com

为什么说桥梁是UIViewRepresentable、Coordinator?
因为要想将UIKit的组件渲染到swift项目中,就需要转换的过程,比如有一个输入框,在swiftui中使用TextField来实现的,但是到UIKit中就需要使用UITextView实现,这个时候就需要使用UIViewRepresentable来协助你进行这个转换过程。
UIViewRepresentable这个协议是必须要实现两个函数
一个是makeUIView函数,用来初始化UITextView这个组件,只会执行一次,用来初始化等操作。
updateUIView是更新函数,SwiftUI 会比较视图层次,当发现MyView有变化的时候 ,自动调用其 updateUIView 方法来更新组件,其中传递的连个参数是uiView和context,_ 是外部参数,也就是参数标签,可以忽略不写,说是为了更加清晰,其实一坨垃圾。uiView就是makeUIView中最后返回的视图组件。context是上下文包含了访问协调器和环境信息等

这个时候再把组件放到swiftui中就可以展示出来了:

如果你的updateUIView函数中,什么内容都不放,那么当你在父组件中修改defaultText的值时候,子组件是不会发生改变的,因为你都没实现更新逻辑,怎么让页面改变?
在第一次加载时,makeUIView 和 updateUIView 都会执行! 但是它们的执行顺序和次数不同:
arduino
MyView init - text: 11 // 1. 初始化
makeCoordinator called // 2. 创建协调器
makeUIView called - text: 11 // 3. 创建 UIView
updateUIView called - text: 11 // 4. 首次更新 ❗️
注意 :updateUIView 在第一次也会被调用!
SwiftUI 的渲染流程:
scss
第一次渲染:
1. 创建 MyView 实例
2. 调用 makeCoordinator() 创建协调器
3. 调用 makeUIView() 创建 UIKit 视图
4. SwiftUI 将视图插入层级后,立即调用 updateUIView()
→ 确保视图状态完全同步
所以在makeUIView中你可以专注于写ui就好,初始化和更新逻辑就放在updateUIView中。
Coordinator又是干啥的?
Coordinator协调器是 UIViewRepresentable 和 UIViewControllerRepresentable 中的核心概念,它在 SwiftUI 和 UIKit 之间充当桥梁和中介。
如果没有这个玩意,你会发现,让你在UITextView中输入的内容改变后,你在父视图中再获取defaultText的值,是没有变为你输入的内容的!这就是数据没有反向绑定!!!!
但是如果你使用swiftui中的TextField组件,你就会发现它已经实现类数据的双向绑定。

Coordinator 协调器是一个自定义类,负责:
objectivec
处理 UIKit 的委托(delegate)和数据源(data source)
管理 UIKit 视图的生命周期事件
在 SwiftUI 和 UIKit 之间传递数据和事件
也就是说,让数据发生变化时,也更新绑定的数据里面的值。
因为你在makeUIView中只是实现了UI,但是没有说这个UI组件当用户输入了内容后,怎么获取里面的值和做什么操作。这个时候,就需要使用 UITextViewDelegate 和 Coordinator 来做了。还有NSObject这个!
NSObject、UITextViewDelegate都是啥
什么是 NSObject?
kotlin
// NSObject 是 Objective-C 运行时的基础类
// 在 Swift 中继承 NSObject 可以让 Swift 类获得 Objective-C 的能力
class Coordinator: NSObject {
// 现在这个类可以:
// 1. 使用 Objective-C 的运行时特性
// 2. 作为代理(delegate)使用
// 3. 使用 KVO(键值观察)
}
为什么需要 NSObject?
// ❌ 错误:纯 Swift 类不能作为 UIKit 的代理
class PureSwiftCoordinator: UITextViewDelegate {
// 编译错误:UIKit 期望 Objective-C 兼容的对象
}
// ✅ 正确:继承 NSObject 后就可以作为代理
class Coordinator: NSObject, UITextViewDelegate {
// 正常工作
}
NSObject 提供的能力:
class Coordinator: NSObject {
// 1. Objective-C 运行时支持
// 2. 内存管理(引用计数)
// 3. 方法派发(动态派发)
// 4. 序列化和反序列化支持
// 5. KVO/KVC 支持
}
UITextViewDelegate 的作用
swift
什么是 UITextViewDelegate?
// UITextViewDelegate 是一个协议(Protocol)
// 定义了 UITextView 可以调用的方法
protocol UITextViewDelegate: NSObjectProtocol {
// 文本变化时调用
optional func textViewDidChange(_ textView: UITextView)
// 开始编辑时调用
optional func textViewDidBeginEditing(_ textView: UITextView)
// 结束编辑时调用
optional func textViewDidEndEditing(_ textView: UITextView)
// 更多方法...
}
代理模式的工作原理:
// UIKit 的设计模式:
class UITextView: UIView {
weak var delegate: UITextViewDelegate? // 持有代理的弱引用
func userDidTypeSomething() {
// 当用户输入时...
delegate?.textViewDidChange?(self) // 通知代理
}
}
// 我们的 Coordinator 实现代理:
class Coordinator: NSObject, UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
print("用户输入了: \(textView.text)")
}
}
为什么需要两者结合?
// 1. Coordinator 继承 NSObject,获得 Objective-C 兼容性 class Coordinator: NSObject { // ✅ 第一步:继承 NSObject } // 2. 遵守 UITextViewDelegate 协议,承诺实现某些方法 class Coordinator: NSObject, UITextViewDelegate { // ✅ 第二步:遵守协议 func textViewDidChange(_ textView: UITextView) { // 实现协议方法 } } // 3. 在 makeUIView 中设置代理 func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.delegate = context.coordinator // ✅ 第三步:设置代理 return textView }
Coordinator又是干啥的?
Coordinator是协调器,用于继承 NSObject, UITextViewDelegate然后实现其中的方法,然后作为UITextView的代理,当UITextView文本内容发生变化后,就委托代理里面的方法,比如刚开始输入和已修改等操作函数。
设置代理的方法在makeUIView中实现:

如果你不实现这个UITextViewDelegate协议,就无法作为UITextView的代理,并报错:

在Coordinator中实现的textViewDidChange函数,然后在这个函数中实现数据的反向修改:

这样整个流程下来,就实现了数据的双向绑定
大家好,我是1024小神,技术群 / 私活群 / 股票群 或 交朋友 都可以私信我。 如果你觉得本文有用,一键三连 (点赞、评论、关注),就是对我最大的支持~