英文:
how to push ViewController from inside UIHostingController's SwiftUI view using pushViewController?
问题
我有一个使用UIHostingController
来显示SwiftUI视图的UiKit应用程序。在这个视图中有一个按钮,我想要使用它来导航到另一个ViewController。我如何可以从这个SwiftUI视图内部推出一个新的ViewController?(或更一般地说:我如何可以从SwiftUI视图内部调用ViewController中的函数?)
当然,我可以在SwiftUI内部使用NavigationView,但我想要尽可能多地使用UiKit,以便在业务逻辑和UI之间实现清晰的分离。
import UIKit
import SwiftUI
class MainViewController: UIViewController {
var viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
addView()
}
func addView() {
let testView = SwiftUIView(viewModel: viewModel)
let controller = UIHostingController(rootView: testView)
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controller.view)
controller.didMove(toParent: self)
NSLayoutConstraint.activate([
controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
func navigate() { // 我如何可以从SwiftUI的testView视图内部调用这个函数?
let otherView = Text("test")
let nextVc = UIHostingController(rootView: otherView)
navigationController?.pushViewController(nextVc, animated: true)
}
}
SwiftUI部分如下:
import SwiftUI
struct SwiftUIView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Button {
// 推出新的视图控制器
// 你可以在这里调用MainViewController的navigate()函数
} label: {
Text("go")
}
}
}
英文:
I have a UiKit app using a UIHostingController
to show a SwiftUI view. In this view there is a button, which I want to use to navigate to another ViewController. How can I push a new viewController from inside this SwiftUI view? (or more generally: how can I call a function from my ViewController from inside the SwiftUI view?)
Of course I could just NavigationView inside SwiftUI, but I want to do most with UiKit, in order to have clean separation between business logic and UI.
import UIKit
import SwiftUI
class MainViewController: UIViewController {
var viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
addView()
}
func addView() {
let testView = SwiftUIView(viewModel: viewModel)
let controller = UIHostingController(rootView: testView)
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controller.view)
controller.didMove(toParent: self)
NSLayoutConstraint.activate([
controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
func navigate() { // how do I call this from inside SwiftUI testView view?
let otherView = Text("test")
let nextVc = UIHostingController(rootView: otherView)
navigationController?.pushViewController(nextVc, animated: true)
}
}
with the SwiftUI being something like:
import SwiftUI
struct SwiftUIView: View {
@ObservedObject var viewModel: ViewModel
var body: some View {
Button {
// push new view controller
} label: {
Text("go")
}
}
}
答案1
得分: 1
使你的MainViewController成为ObservableObject
在testView
上设置环境对象
在视图内部使用@EnvironmentObject var parent: MainViewController
访问你的环境对象
class MainViewController: UIViewController, ObservableObject {
var viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
addView()
}
func addView() {
let testView = SwiftUIView(viewModel: viewModel)
let controller = UIHostingController(rootView: testView.environmentObject(self))
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controller.view)
controller.didMove(toParent: self)
NSLayoutConstraint.activate([
controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
struct SwiftUIView: View {
@EnvironmentObject var parent: MainViewController
var body: some View {
Button {
// 推入新的视图控制器
parent.navigationController?.pushViewController(<#T##viewController: UIViewController##UIViewController#>, animated: <#T##Bool#>)
} label: {
Text("go")
}
}
}
英文:
Make your MainViewController as ObservableObject
Set environment object on testView
Access your environment object inside your view using @EnvironmentObject var parent: MainViewController
class MainViewController: UIViewController, ObservableObject {
var viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
addView()
}
func addView() {
let testView = SwiftUIView(viewModel: viewModel)
let controller = UIHostingController(rootView: testView.environmentObject(self))
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controller.view)
controller.didMove(toParent: self)
NSLayoutConstraint.activate([
controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
struct SwiftUIView: View {
@EnvironmentObject var parent: MainViewController
var body: some View {
Button {
// push new view controller
parent.navigationController?.pushViewController(<#T##viewController: UIViewController##UIViewController#>, animated: <#T##Bool#>)
} label: {
Text("go")
}
}
}
答案2
得分: 0
调用此函数在你的按钮点击事件上。尽量使这个函数全局可用,这样你可以从任何SwiftUI视图中访问它。
func navigateToViewController(view: View)
{
let newVC = UIHostingController(rootView: view)
newVC.modalPresentationStyle = .overCurrentContext
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
UIApplication.shared.windows[0].rootViewController!.view.window!.layer.add(transition, forKey: kCATransition)
UIApplication.shared.windows[0].rootViewController!.present(newVC, animated: false, completion: nil)
}
英文:
call this function on your button-click event. try to make this function global so you can access it from every swiftUI View.
func navigateToViewController(view : any View)
{
let newVC = UIHostingController(rootView: view)
newVC.modalPresentationStyle = .overCurrentContext
let transition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromRight
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
UIApplication.shared.windows[0].rootViewController!.view.window!.layer.add(transition, forKey: kCATransition)
UIApplication.shared.windows[0].rootViewController!.present(newVC, animated: false, completion: nil)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论