![](/img/trans.png)
[英]How to push to UIViewController from SwiftUI View that is in NavigationController
[英]Push to UIViewController from SwiftUI
我的应用程序是UIKit
和SwiftUI
的混合SwiftUI
。 我有一个用例,用户可能需要点击SwiftUI.View
的Button
但推送到UIViewController
或另一个UIHostingController
。
我的项目使用Storyboard
。
我正在使用UINavigationController
和UITabBarController
。
我正在考虑两种情况。
1.) 从我在主屏幕上的初始启动开始,我可以点击一个按钮,并在其操作中:
let vc = UIHostingController(rootView: RootView())
self.navigationController?.pushViewController(vc, animated: true)
这按预期工作。
2.) 我点击一个不同的选项卡,它默认为我的SwiftUI
RootView,它托管在我在Storyboard
使用的自定义UIHostingController
中。 在这里,如果我点击一个按钮来触发推送,它不会推送。 我只看到我正在更新的View
。
我也在使用自定义UINavigationController
。 从我的Storyboard
,选项卡关系转到自定义UINavigationController
& 然后它的根是适当的UIViewController
。 在一种情况下,虽然它是我的自定义UIHostingController
因此我可以最初从选项卡选择加载SwiftUI
视图。
这是我尝试从我的 SwiftUI 视图处理推送到视图控制器的操作:
final class AppData: ObservableObject {
weak var window: UIWindow? // Will be nil in SwiftUI previewers
init(window: UIWindow? = nil) {
self.window = window
}
public func pushViewController(_ viewController: UIViewController, animated: Bool = true) {
let nvc = window?.rootViewController?.children.first?.children.first as? UINavigationController
nvc?.pushViewController(viewController, animated: animated)
}
}
// This is what is triggered from the Button action.
func optionSelected(option: String) {
if let optionId = Common.getIDByOption(option: option) {
let vc = UIHostingController(rootView: RootView())
appData.pushViewController(vc, animated: true)
}
}
怎么了:
UIHostingController
。如果您以UITabBarController
和UINavigationController
处理导航的方式混合UIKit
和SwiftUI
。 我建议你剪掉NavigationView
和NavigationLink
。 背后的原因很简单。 SwiftUI.View
将在每次切换到选项卡时重新创建。 因此,您将从头开始。 您可以四处走动,但在这种情况下,使用UINavigationController
会更容易。
假设您的应用程序有两个选项卡。 我会把SwiftUI.View
在UIHostingController
,然后在UINavigationController
。 在SwiftUI.View
我将关闭let onTap: () -> Void
每当您需要将下一个UIHostingController
或UIViewController
推送到UINavigationController
时都会调用它。
例子
//: A UIKit based Playground for presenting user interface
import UIKit
import SwiftUI
import PlaygroundSupport
final class MainViewController: UITabBarController {
let firstTab: UINavigationController = {
let navigationController = UINavigationController()
navigationController.tabBarItem = UITabBarItem(title: "First", image: nil, tag: 1)
return navigationController
}()
let secondTab: UINavigationController = {
let navigationController = UINavigationController()
navigationController.tabBarItem = UITabBarItem(title: "Second", image: nil, tag: 1)
return navigationController
}()
override func viewDidLoad() {
super.viewDidLoad()
setUpFirstTab()
setUpSecondTab()
viewControllers = [firstTab, secondTab]
}
func setUpFirstTab() {
let firstView = FirstView { number in
let secondViewHostingController = UIHostingController(rootView: SecondView(number: number))
self.firstTab.pushViewController(secondViewHostingController, animated: true)
}
let firstViewHostingController = UIHostingController(rootView: firstView)
firstTab.tabBarItem = UITabBarItem(title: "First", image: nil, tag: 1)
firstTab.viewControllers = [firstViewHostingController]
}
func setUpSecondTab() {
secondTab.tabBarItem = UITabBarItem(title: "Second", image: nil, tag: 2)
secondTab.viewControllers = [FirstViewController()]
}
}
// Views for the first tab
struct FirstView: View {
let onTap: (Int) -> Void
@State var number: Int = 0
var body: some View {
VStack {
Stepper("Number \(number)", value: $number)
Button {
onTap(number)
} label: {
Text("Go to the next view")
}
}
}
}
struct SecondView: View {
let number: Int
var body: some View {
Text("Final view with number \(number)")
}
}
// Views controllers for the second tab
final class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button: UIButton = UIButton(type: .roundedRect, primaryAction: UIAction(title: "show next view controller") { _ in
self.navigationController?.pushViewController(SecondViewController(), animated: true)
})
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
}
final class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemPink
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.