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