簡體   English   中英

如何在沒有 NavigationLink 的情況下導航到 SwiftUI 中的視圖

[英]How to navigate to a View in SwiftUI without NavigationLink

我是 SwiftUI 的新手,想從任何其他視圖導航到 SwiftUI 中的“主頁”視圖。 我創建了一個主頁按鈕,該按鈕被添加到多個視圖的導航欄中。 主頁按鈕返回到“主頁”視圖,但導航鏈接無法正確導航並顯示錯誤數據。

我已經閱讀了其他有類似問題的人的多個答案,但答案至少已有兩年歷史,並且 SwiftUI 從那時起發生了很大變化。 我試圖實現許多答案,但總是遇到其他問題。 某些功能已被棄用,我正在尋找更具前瞻性的解決方案。

這是一些顯示問題的代碼。 在此示例中,我在 NavigationLink 中使用 isActive 參數來觸發主頁按鈕,但這似乎會破壞 NavigationLink。 我也嘗試過使用標簽和選擇參數並獲得相同的結果。 通過閱讀其他回復,我相信在“ProductFamilyView”中使用 ForEach 語句是引用錯誤數據的問題。 但是,在此應用程序中,我需要使用 ForEach 語句來顯示產品系列。

如果我嘗試調用 ProductFamilyView(),什么也不會發生。 在此示例中,我想導航回“ProductFamilyView”。 是否有另一種方法可以在不使用 NavigationLink 的情況下導航到此視圖?

import SwiftUI
import Combine

class Navigation: ObservableObject {
    @Published var productFamilyIsActive : Bool = false
}

struct ContentView: View {
    
    @StateObject var navigation = Navigation()
    
    var body: some View {
        NavigationView {
            VStack {
                LoginButtonView(buttonText: "Login")
            }
        }
        .environmentObject(navigation)
        .navigationViewStyle(StackNavigationViewStyle() )
    }
}
struct LoginButtonView: View {
    
    @State private var navigated : Bool = false
    var buttonText : String
    
    var body: some View {
        Button(action: {
            self.navigated.toggle()
        }, label: {
            Text("\(buttonText)")
        })
        .navigationBarBackButtonHidden(true)
        NavigationLink(destination: ProductFamilyView(), isActive: $navigated ) {
            EmptyView()
        }
    }
}
struct ProductFamilyView: View { //This is my home view
    
    private var productFamilies = ProductFamilyViewModel.loadData()
    
    var body: some View {
        List {
            ForEach(productFamilies) { (product) in
                ProductFamilyRow(productFamily: product.productFamily)
            }
        }
        .navigationTitle("Product Families")
        .navigationBarTitleDisplayMode(.inline)
        .navigationBarBackButtonHidden(true)
    }
}
struct ProductFamilyRow: View {
    
    @EnvironmentObject var navigation : Navigation
    @State var productFamily : String

    var body: some View {
        NavigationLink(destination: PartNumberView(productFamily: productFamily), isActive: $navigation.productFamilyIsActive) {
            Text("\(productFamily)")
        }
        .isDetailLink(false)
    }
}
struct PartNumberView: View {
    
    @State var productFamily: String
    
    var productDetails = ProductViewModel.loadData()
        
    var body: some View {
        List {
            ForEach(productDetails) { (productDetail) in
                if productFamily == productDetail.productFamily {
                    NavigationLink(destination: PartNumberRow(productDetail: productDetail)) {
                        Text("\(productDetail.partNumber)")
                    }
                }
            }
        }
        .navigationTitle("\(productFamily)")
        .navigationBarItems(trailing: HomeButtonView() )
    }
}
struct PartNumberRow: View {
    
    @State var productDetail : ProductViewModel
    
    var body: some View {
        List {
            Text("Description: \(productDetail.description)")
            NavigationLink(destination: ColorView(colorOptions: productDetail.colorOptions)) {
                Text("Color Options")
            }
        }
        .navigationTitle("\(productDetail.partNumber)")
        .navigationBarItems(trailing: HomeButtonView() )
    }
}
struct ColorView: View {
    
    @State var colorOptions : [Item]
    
    var body: some View {
        List {
            ForEach(colorOptions) { (color) in
                Text("\(color.name)")
            }
        }
        .navigationBarItems(trailing: HomeButtonView() )
    }
}
struct HomeButtonView: View {
    
    @EnvironmentObject var navigation : Navigation
    
    var body: some View {
        
        Button(action: {
            self.navigation.productFamilyIsActive.toggle()
        }, label: {
            Image(systemName: "house")
        })
        .environmentObject(navigation)
    }
}
class ProductFamilyViewModel: ObservableObject, Identifiable {
    
    var id = UUID().uuidString
    var productFamily : String = ""
    
    init(productFamily: String) {
        self.productFamily = productFamily
    }
    static func loadData() -> [ProductFamilyViewModel] {
        
        let products = ["Product Family 1", "Product Family 2", "Product Family 3"]
        var productFamilies : [ProductFamilyViewModel] = []
        
        for product in products {
            productFamilies.append(ProductFamilyViewModel(productFamily: product))
        }
        return productFamilies
    }
}
struct Item: Identifiable, Codable {

    var id : String {
        self.name
    }
    var name : String
}
struct Product: Identifiable {
    
    var id = UUID().uuidString
    var partNumber    : String = "part number"
    var productFamily : String = "product family"
    var description   : String = "description"
    var colorOptions  : [Item] = []
}
class ProductViewModel: ObservableObject, Identifiable {
    
    var id = UUID().uuidString
    var partNumber    : String
    var productFamily : String
    var description   : String
    var colorOptions  : [Item]
    
    init(model: Product) {
        self.partNumber    = model.partNumber
        self.productFamily = model.productFamily
        self.description   = model.description
        self.colorOptions  = model.colorOptions
    }
    static func loadData() -> [ProductViewModel] {
        
        let colors = [Item(name: "red"), Item(name: "white"), Item(name: "blue")]
        
        let productDetails : [ProductViewModel] = [
            ProductViewModel( model: Product(
                partNumber: "100-1111-101",
                productFamily: "Product Family 1",
                description: "Part Number 100-1111-101",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "100-1111-102",
                productFamily: "Product Family 1",
                description: "Part Number 100-1111-102",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "100-1111-103",
                productFamily: "Product Family 1",
                description: "Part Number 100-1111-103",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "200-1111-101",
                productFamily: "Product Family 2",
                description: "Part Number 200-1111-101",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "200-1111-102",
                productFamily: "Product Family 2",
                description: "Part Number 200-1111-102",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "200-1111-103",
                productFamily: "Product Family 2",
                description: "Part Number 200-1111-103",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "300-1111-101",
                productFamily: "Product Family 3",
                description: "Part Number 300-1111-101",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "300-1111-102",
                productFamily: "Product Family 3",
                description: "Part Number 300-1111-102",
                colorOptions: colors)
            ),
            ProductViewModel( model: Product(
                partNumber: "300-1111-103",
                productFamily: "Product Family 3",
                description: "Part Number 300-1111-103",
                colorOptions: colors)
            )
        ]
        return productDetails
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(Navigation())
    }
}

首先 - 恭喜:這是第一個如此復雜的代碼,可以在復制/粘貼到 Xcode 時完美運行......不經常發生:)

對於你的問題:
你幾乎擁有它。 唯一的問題是你的productFamilyIsActive是一個 Bool——它只能保存一個選定的 NavigationLink 上的信息,你有 3 個。但如果你將它更改為可選選擇,它就可以:

class Navigation: ObservableObject {
    @Published var productFamilyIsActive : String? = nil // here
}

為此,您在此處的 NavigationLink 上使用不同的初始化:

struct ProductFamilyRow: View {
    
    @EnvironmentObject var navigation : Navigation
    @State var productFamily : String
    
    var body: some View {
        NavigationLink(destination: PartNumberView(productFamily: productFamily),
                       tag: productFamily, // here
                       selection: $navigation.productFamilyIsActive) { // and here
            Text("\(productFamily)")
        }
        .isDetailLink(false)
    }
}

最后你不要設置為 false 而是在這里設置為 nil :

struct HomeButtonView: View {
    
    @EnvironmentObject var navigation : Navigation
    
    var body: some View {
        Button(action: {
            self.navigation.productFamilyIsActive = nil // here
        }, label: {
            Image(systemName: "house")
        })
            .environmentObject(navigation)
    }
}

瞧!

暫無
暫無

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

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