[英]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.