簡體   English   中英

在同一結構中使用 EnvironmentObject 和 Binding? [初學者]

[英]Using EnvironmentObject and Binding in same struct? [Beginner]

我設法設置了一個 Navigationstack,我以編程方式使用它來插入/刪除視圖。 在我的 FindOrderView 中,我想使用綁定將變量“ordernumber”傳遞到我的 LoadingScreen(View),但我收到一條錯誤消息,指出我的 LoadingScreen 不符合類型“Equatable”。 我可能做錯了什么,還有其他有效的方法可以使它正常工作嗎?

我是 SwiftUi 的完全初學者,但在此處發布之前已經搜索了幾個小時。 感謝您的幫助。

NavigationRouter(用於控制視圖層的類)

import Foundation
import SwiftUI

enum Route: Hashable {
    case ContentView
    case View1
}


final class NavigationRouter: ObservableObject {
    @Published var navigationPath = NavigationPath()
    
    func pushView(route: Route) {
        navigationPath.append(route)
    }
    
    func popToRootView() {
        navigationPath = .init()
    }
    
    func popToSpecificView(k: Int) {
        navigationPath.removeLast(k)
        
    }

}

Mainapp(應用程序從這里開始但立即跳轉到 MainScreenView())

import SwiftUI

@main
struct AvhamtningApp: App {
    
    @StateObject var router = NavigationRouter()
    
    var body: some Scene {
        WindowGroup {
            NavigationStack(path: $router.navigationPath) {
                MainScreenView()
                    .navigationDestination(for: Route.self) { route in
                        switch route {
                        case .ContentView:
                            MainScreenView()
                        case .View1:
                            FindOrderView()
                        }
                    }
            }.environmentObject(router)
        }
    }
} 

MainScreenView(帶有名為“獲取訂單”的按鈕的視圖,可將您帶到 View1 (FindOrderView))

import SwiftUI

struct MainScreenView: View {
    
    @EnvironmentObject var router: NavigationRouter
    
    var body: some View {
            VStack() {
                Text("Testing")
                    .font(.largeTitle)
                    .fontWeight(.heavy)
                    .foregroundColor(.yellow)
                    .padding(.top, 50)
                
                Spacer()
                PrimaryButton(text: "Get Order")
                    .onTapGesture {
                        router.pushView(route: .View1)
                    }
                Spacer()
                
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color(.white)).ignoresSafeArea(.all)
    }
}

struct MainScreenView_Previews: PreviewProvider {
    static var previews: some View {
        MainScreenView()
    }
}

FindOrderView(使用鍵盤查看,如果輸入 7 位數字,則應該將您帶到 Loadingscreen() 並使用變量“ordernumber”作為綁定)

import SwiftUI

var list = [["1","2","3"],["4","5","6"],["7","8","9"],["","0","⌫"]]

struct FindOrderView: View {
    @State private var ordernumber: String = ""
    @EnvironmentObject var router: NavigationRouter
    
    var body: some View {
        
        VStack(spacing: 25) {
            Text(ordernumber)
                .font(.largeTitle)
                .foregroundColor(.black)
                .onChange(of: ordernumber) { newValue in
                    if ordernumber.count >= 7 {
                        router.navigationPath.append(LoadingScreen(ordernumber: $ordernumber))
                    }
                }
            Spacer()
            ForEach(list.indices, id: \.self) { listindex in
                
                HStack{
                    ForEach(list[listindex], id: \.self) { variableindex in
                        Text(variableindex)
                            .foregroundColor(.blue)
                            .font(.system(size: 60))
                            .onTapGesture(perform: {
                                if variableindex == "⌫" && !ordernumber.isEmpty {
                                    ordernumber.removeLast()
                                }
                                else if ordernumber.count >= 7 {return}
                                
                                else if variableindex == "⌫" {
                                    ()
                                }
                                else {
                                    ordernumber += variableindex
                                }})
                        .frame(maxWidth: .infinity)
                    }
                    
                    }
                }
            
            }.background(.white)
        
        }
    
    }


struct FindOrderView_Previews: PreviewProvider {
    static var previews: some View {
        FindOrderView()
    }
}
 

LoadingScreen(這是我收到錯誤“Type 'LoadingScreen' does not conform to protocol 'Equatable'”的地方)

import SwiftUI

struct LoadingScreen: Hashable, View {
    
    
    @EnvironmentObject var router: NavigationRouter
    @Binding var ordernumber: String
    
    var body: some View {
        ZStack{
            Text("Loading...")
                .font(Font.custom("Baskerville-Bold", size: 50))
                .foregroundColor(.orange)
                .padding(.bottom, 200)
            
            ProgressView()
                .progressViewStyle(CircularProgressViewStyle(tint: .orange))
                .scaleEffect(2)
            

        }.frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color(.white)).ignoresSafeArea(.all)
    }
}


struct LoadingScreen_Previews: PreviewProvider {
    static var previews: some View {
        LoadingScreen(ordernumber: .constant("constant"))
    }
}

所以應用程序在MainScreenView上啟動,因為它被設置為 NavigationStack 的根。

您的導航問題是您試圖將視圖作為導航目標值發送,但您需要發送路由值,並打開navigationDestination以生成要推送的視圖。

因此,在您的Route枚舉中,添加用於加載的路由:

case loading(orderNumber: String)

然后在您的NavigationLink中發送新路線:

NavigationLink(value: Route.loadingScreen(orderNumber: orderNumber)

然后在您的navigationDestination視圖修飾符中:

.navigationDestination(for: Route.self) { route in
    switch route {
        case .ContentView:
            MainScreenView()
        case .View1:
            FindOrderView()
        case .loading(let orderNumber):
            LoadingScreen(orderNumber: orderNumber)
                .environmentObject(router)
        }
}

希望這可以幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM