[英]I found two ways to manage views in SwiftUI, but I don't know what the difference is and I don't know which is the better way
This class goes into all methods the same.这个类进入所有方法都是一样的。
import SwiftUI
class NavModel: ObservableObject {
@Published var fullDissmiss:Bool = true
}
first way第一种方式
import SwiftUI
@main
struct trainingApp: App {
var body: some Scene {
WindowGroup {
RootNavView()
}
}
}
import SwiftUI
struct RootNavView: View {
@ObservedObject var navModel = NavModel()
var body: some View {
if(navModel.fullDissmiss == true){
FirstRouteView(navModel: navModel)
} else {
SecondRouteView(navModel: navModel)
}
}
}
import SwiftUI
struct FirstRouteView: View {
var navModel: NavModel
var body: some View {
VStack{
Text("This First Route View")
Button("Full dissmiss and second view show up"){
navModel.fullDissmiss = false
}
}
}
}
import SwiftUI
struct SecondRouteView: View {
var navModel: NavModel
var body: some View {
VStack{
Text("This Second Route View")
Button("Full dissmiss and first view show up"){
navModel.fullDissmiss = true
}
}
}
}
second way第二种方式
import SwiftUI
@main
struct trainingApp: App {
var body: some Scene {
WindowGroup {
SGRootNavigationView(){}
}
}
}
import SwiftUI
struct SGRootNavigationView<Content>: View where Content: View {
let cancellable = NotificationCenter.default.publisher(for: Notification.Name("SGGoToRoot"), object: nil)
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
print("SGRootNavigationView init()")
self.content = content
}
@State var goToRoot:Bool = false
var body: some View {
return
Group{
if goToRoot == false{
NavigationView {
FirstRouteView()
}
} else {
NavigationView {
SecondRouteView()
}
}
}.onReceive(cancellable, perform: {_ in
DispatchQueue.main.async {
print("self.goToRoot : ", self.goToRoot)
self.goToRoot.toggle()
print("self.goToRoot : ", self.goToRoot)
}
})
}
}
import SwiftUI
struct SGNavigationChildsView<Content>: View where Content: View {
let notification = Notification(name: Notification.Name("SGGoToRoot"))
var fullDissmiss:Bool{
get{ return false }
set{ if newValue {self.goToRoot()} }
}
let content: () -> Content
init(fullDissmiss:Bool, @ViewBuilder content: @escaping () -> Content) {
print("SGNavigationChildsView init")
print("content : ", content)
print("fullDissmiss : ", fullDissmiss)
self.content = content
self.fullDissmiss = fullDissmiss
}
var body: some View {
content()
}
func goToRoot(){
print("goToRoot : ", goToRoot)
NotificationCenter.default.post(self.notification)
}
}
import SwiftUI
struct FirstRouteView: View {
@ObservedObject var navModel = NavModel()
var body: some View {
SGNavigationChildsView(fullDissmiss: self.navModel.fullDissmiss){
VStack{
Text("This First Route View")
Button("Full dissmiss and second view show up"){
navModel.fullDissmiss = true
}
}
}
}
}
import SwiftUI
struct SecondRouteView: View {
@ObservedObject var navModel = NavModel()
var body: some View {
SGNavigationChildsView(fullDissmiss: self.navModel.fullDissmiss){
VStack{
Text("This Second Route View")
Button("Full dissmiss and first view show up"){
navModel.fullDissmiss = true
}
}
}
}
}
Is it difficult to see that the first method manages the root view?很难看出第一种方法管理根视图吗?
The first method is easy, but I don't know if it can be managed simply like that.第一种方法简单,不知道能不能这么简单的管理。
I don't have enough knowledge to tell which one is the better way.我没有足够的知识来判断哪种方法更好。
Is the second method better because FirstRouteView and SecondRouteView are managed in SGNavigationChildsView and those structures are managed in one structure (SGRootNavigationVIew)?第二种方法是否更好,因为 FirstRouteView 和 SecondRouteView 在 SGNavigationChildsView 中管理,而这些结构在一个结构 (SGRootNavigationVIew) 中管理?
I'm using ObservableObject way but depending on your use case it might be a good idea to use the first method:我正在使用 ObservableObject 方式,但根据您的用例,使用第一种方法可能是个好主意:
enum Page {
case newAccount
case existingAccount
}
@MainActor
class ViewRouter: ObservableObject {
@Published var currentPage: Page = .newAccount
}
Notice that I am adding MainActor to make sure that I update views in main thread.
请注意,我添加 MainActor 以确保我更新主线程中的视图。
In main.swift:在 main.swift 中:
@main
struct YOUR_APP_NAME: App {
@StateObject nonisolated var viewRouter = ViewRouter()
var body: some Scene {
WindowGroup {
MainView()
.environmentObject(viewRouter)
}
}
}
Read more about
nonisolated
click here阅读更多关于
nonisolated
点击这里
struct MainView: View {
@EnvironmentObject var viewRouter: ViewRouter
var body: some View {
switch viewRouter.currentPage {
case .newAccount:
// LoginView()
case .existingAccount:
// ContentView()
// .transition(.scale) <-- Add animation when changing view
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.