简体   繁体   English

我在 SwiftUI 中找到了两种管理视图的方法,但我不知道有什么区别,也不知道哪种方法更好

[英]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) 中管理?

  1. First method is for view presentation第一种方法用于视图演示
  2. Second method is for managing navigation controller stack第二种方法是管理导航控制器堆栈

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.

相关问题 我用 forEach 创建了一个 Circle,但我不知道如何检查其中的数据。 /SwiftUI - I created a Circle with forEach but I don't know the way to check the data in it. /SwiftUi 当我不知道数组中有哪些对象时,是否为循环? - For loop when I don't know what objects are in an array? 使用cpp扩展的Objective-C,我不知道我在做什么 - Objective-C with cpp extensions, I don't know what I'm doing 我不知道对于objective-c中的字面范围我应该避免哪些模块 - I don't know what patterns of block I should avoid for the literal scope in objective-c 当弹丸击中两个“怪物”时,didBeginContact方法崩溃。 我知道为什么,但我不知道如何避免 - When projectile hits two “monsters” the didBeginContact method crashes. I know why but i don't know how to avoid it 我不知道为什么在swift3中没有调用viewForHeaderInSection - I don't know why viewForHeaderInSection is not called in swift3 我不知道如何将弹出框与按钮对齐 - I don't know how to align my popovers to button 我不知道为什么这个表视图代码崩溃了 - i don't know why this table view code crashes 我不知道为什么结果不是我想的 - I don't know why the result is not my have thought 如果不知道其密钥,如何在Firebase中更新节点? - How to update a node in Firebase if I don't know its key?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM