繁体   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

这个类进入所有方法都是一样的。

import SwiftUI

class NavModel: ObservableObject {
    @Published var fullDissmiss:Bool = true
}

第一种方式

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
                }
        }
    }
}

第二种方式

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
                }
            }
        }
    }
}

很难看出第一种方法管理根视图吗?

第一种方法简单,不知道能不能这么简单的管理。

我没有足够的知识来判断哪种方法更好。

第二种方法是否更好,因为 FirstRouteView 和 SecondRouteView 在 SGNavigationChildsView 中管理,而这些结构在一个结构 (SGRootNavigationVIew) 中管理?

  1. 第一种方法用于视图演示
  2. 第二种方法是管理导航控制器堆栈

我正在使用 ObservableObject 方式,但根据您的用例,使用第一种方法可能是个好主意:

enum Page {
    case newAccount
    case existingAccount
}
@MainActor
class ViewRouter: ObservableObject {

    @Published var currentPage: Page = .newAccount
}

请注意,我添加 MainActor 以确保我更新主线程中的视图。

在 main.swift 中:

@main
struct YOUR_APP_NAME: App {

    @StateObject nonisolated var viewRouter = ViewRouter()

    var body: some Scene {
        
        WindowGroup {

            MainView()
                .environmentObject(viewRouter)
        }
    }
}

阅读更多关于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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM