另一个问题标题可能是“如何将UIHostingController的视图添加为UIView的子视图?” 。
我正在创建一个新的UI组件,很想尝试SwiftUI。下图是当前视图结构。UIView是我现在正在使用的(右上),而SwiftUI视图是我尝试使用的(右下)。
观看了WWDC 2019中的所有SwiftUI视频之后,我仍然不知道如何使用SwiftUI视图并将其放在应该将UIView实例放到哪里。
我从“ Integrating SwiftUI”演讲中注意到,有一个NSHostingView
适用于macOS的https://developer.apple.com/documentation/swiftui/nshostingview#,这让我想知道是否有类似的东西或可以实现的替代方法它。
我读了类似现有UIKit应用程序中的“ 包括SwiftUI视图”之类的问题,其中提到SwiftUI和UIKit可以一起使用UIHostingController
。但是,我想做的是仅采用一小段SwiftUI,并将其放入我现有的UIKit视图组件中,而不是将其用作控制器。
我是iOS开发的新手,如果有一种方法可以将视图控制器用作UIView视图,请发表评论。谢谢。
视图控制器不仅适用于顶级场景。我们通常将视图控制器放在视图控制器中。它被称为“视图控制器包含”和/或“子视图控制器”。(顺便说一句,视图控制器容器通常是抵抗传统UIKit应用程序中的视图控制器膨胀,将复杂的场景分解为多个视图控制器的一种好方法。)
所以,
继续使用UIHostingController
:
let cOntroller= UIHostingController(rootView: ...)
和;
添加视图控制器,然后可以将托管控制器添加为子视图控制器:
addChild(controller) view.addSubview(controller.view) controller.didMove(toParent: self)
显然,您还要frame
为主机控制器设置或布局约束view
。
有关将一个视图控制器嵌入另一个视图控制器的一般信息,请参见文档的“ 实现容器视图控制器”部分。UIViewController
例如,假设我们有一个SwiftUI视图来渲染一个带有文本的圆:
struct CircleView : View { @ObjectBinding var model: CircleModel var body: some View { ZStack { Circle() .fill(Color.blue) Text(model.text) .color(Color.white) } } }
假设这是我们视图的模型:
import Combine class CircleModel: BindableObject { var didChange = PassthroughSubject() var text: String { didSet { didChange.send() } } init(text: String) { self.text = text } }
然后,我们的UIKit视图控制器可以添加SwiftUI视图,在中设置其框架/约束UIView
,并根据需要更新其模型:
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)" } } }