[英]SwiftUI View not updating its state when embedded in UIView (using UIHostingController)
[英]In SwiftUI, how to use UIHostingController inside an UIView or as an UIView?
另一个问题标题可能是“如何将 UIHostingController 的视图添加为 UIView 的子视图?” .
我正在创建一个新的 UI 组件,并且很想尝试一下 SwiftUI。 下图是当前的视图结构。 UIView 是我现在正在使用的(右上),而 SwiftUI 视图是我尝试使用的(右下)。
在我观看了 WWDC 2019 的所有 SwiftUI 视频之后。我仍然不知道如何使用 SwiftUI 视图并将其放在 UIView 实例应该去的位置。
我从“Integrating SwiftUI”谈话中注意到有一个适用于 macOS 的NSHostingView
, https://developer.apple.com/documentation/swiftui/nshostingview#这让我想知道是否有类似的东西或者有什么替代品实现这一目标。
我阅读了诸如Include SwiftUI views in existing UIKit application 之类的问题,提到 SwiftUI 和 UIKit 可以与UIHostingController
一起玩。 然而,我想做的是只采用一小部分 SwiftUI 并将其放在我现有的 UIKit 视图组件中,而不是将其用作控制器。
我是 iOS 开发的新手,如果有办法可以将视图控制器用作 UIView 视图,请发表评论。 谢谢你。
视图控制器不仅适用于顶级场景。 我们经常将视图控制器放在视图控制器中。 它被称为“视图控制器包含”和/或“子视图控制器”。 (顺便说一句,视图控制器容器通常是对抗传统 UIKit 应用程序中视图控制器膨胀的好方法,将复杂的场景分解为多个视图控制器。)
所以,
继续使用UIHostingController
:
let controller = UIHostingController(rootView: ...)
和;
添加视图控制器然后可以将宿主控制器添加为子视图控制器:
addChild(controller) view.addSubview(controller.view) controller.didMove(toParent: self)
显然,您还需要为宿主控制器的view
设置frame
或布局约束。
有关将一个视图控制器嵌入另一个视图控制器的一般信息,请参阅UIViewController
文档的实现容器视图控制器部分。
例如,假设我们有一个 SwiftUI 视图来渲染一个带有文本的圆圈:
struct CircleView : View {
@ObservedObject var model: CircleModel
var body: some View {
ZStack {
Circle()
.fill(Color.blue)
Text(model.text)
.foregroundColor(Color.white)
}
}
}
假设这是我们视图的模型:
import Combine
class CircleModel: ObservableObject {
@Published var text: String
init(text: String) {
self.text = text
}
}
然后我们的 UIKit 视图控制器可以添加 SwiftUI 视图,在UIView
中设置它的框架/约束,并根据你认为合适的方式更新它的模型:
import UIKit
import SwiftUI
class ViewController: UIViewController {
private weak var timer: Timer?
private var model = CircleModel(text: "")
override func viewDidLoad() {
super.viewDidLoad()
addCircleView()
startTimer()
}
deinit {
timer?.invalidate()
}
}
private extension ViewController {
func addCircleView() {
let circleView = CircleView(model: model)
let controller = UIHostingController(rootView: circleView)
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controller.view)
controller.didMove(toParent: self)
NSLayoutConstraint.activate([
controller.view.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
controller.view.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5),
controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
func startTimer() {
var index = 0
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
index += 1
self?.model.text = "Tick \(index)"
}
}
}
我有一些想法。
UIHostingController
因此:
addChild(hostingViewController)
hostingViewController.view.frame = ...
view.addSubview(hostingViewController.view)
hostingViewController.didMove(toParent: self)
视图控制器总是使用其他视图控制器作为视图。
斯坦福 CS193P, https: //youtu.be/w7a79cx3UaY?t=679
参考
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.