首页 > 解决方案 > 在 SwiftUI 中使用 EnvironmentObject 在视图之间传递数据时遇到问题

问题描述

我无法通过不同的视图传递数据EnvironmentObject。我有一个名为的文件LineupDetails,其中包含以下内容:

import SwiftUI

class TeamDetails: ObservableObject {
    let characterLimit = 3
    @Published var TeamName: String = "" {
        didSet {
            if TeamName.count > characterLimit {
                TeamName = String(TeamName.prefix(characterLimit))
            }
        }
    }
    @Published var TeamColor: Color = .blue
    @Published var hitter1First: String = ""
    @Published var hitter1Last: String = ""
    @Published var hitter2First: String = ""
    @Published var hitter2Last: String = ""
    @Published var hitter3First: String = ""
    @Published var hitter3Last: String = ""
    @Published var hitter4First: String = ""
    @Published var hitter4Last: String = ""
    @Published var hitter5First: String = ""
    @Published var hitter5Last: String = ""
    @Published var hitter6First: String = ""
    @Published var hitter6Last: String = ""
    @Published var hitter7First: String = ""
    @Published var hitter7Last: String = ""
    @Published var hitter8First: String = ""
    @Published var hitter8Last: String = ""
    @Published var hitter9First: String = ""
    @Published var hitter9Last: String = ""
    
    @Published var Hitter1Pos = "P"
    @Published var Hitter2Pos = "C"
    @Published var Hitter3Pos = "1B"
    @Published var Hitter4Pos = "2B"
    @Published var Hitter5Pos = "3B"
    @Published var Hitter6Pos = "SS"
    @Published var Hitter7Pos = "LF"
    @Published var Hitter8Pos = "CF"
    @Published var Hitter9Pos = "RF"
    
}

这些变量通过 中的表格进行编辑SetHomeLineup。我已经排除了与问题无关的视图部分,将它们标记为...

struct SetHomeLineup: View {
    @EnvironmentObject var HomeTeam: TeamDetails

...
    
var body: some View {
    HStack {
            TextField("Name", text: $HomeTeam.hitter1First)
            TextField("Last Name", text: $HomeTeam.hitter1Last)
                    Picker(selection: $HomeTeam.Hitter1Pos, label: Text("")) {
                            ForEach(positions, id: \.self) {
                                    Text($0)
                    }
            }
    }
    HStack {
            TextField("Name", text: $HomeTeam.hitter2First)
            TextField("Last Name", text: $HomeTeam.hitter2Last)
                    Picker(selection: $HomeTeam.Hitter2Pos, label: Text("")) {
                            ForEach(positions, id: \.self) {
                                    Text($0)
                    }
            }
    }
        ...
}
// and textfields so on until Hitter9, first and last

现在,当我尝试将上述文本字段的输入值包含到不同的视图中时,使用这样的代码,视图总是显示为空以匹配字符串的默认值。

struct GameView: View {
    @EnvironmentObject var HomeTeam: TeamDetails
    
    ...
    
    var body: some View {
        Text(HomeTeam.hitter1First)
    }
}

有人可以告诉我我做错了什么吗?我尝试在一个新项目中使用类似的代码,它似乎工作得很好,所以我很难过。

编辑:

我的视图是这样实例化的:应用程序的第一个视图是 SetAwayLineup,它包括一个到 SetHomeLineup 的 NavigationLink,就像这样。

var details = TeamDetails()
NavigationLink(destination: SetHomeLineup().environmentObject(details), isActive: self.$lineupIsReady) {

同样,SetHomeLineup 包含一个指向 GameView 的导航链接,如下所示

var details = TeamDetails()
NavigationLink(destination: GameView().environmentObject(details), isActive: self.$lineupIsReady) {

两个屏幕都有一个 AwayLineup 和 HomeLineup 的 EnvironmentObject,我试图将它们调用到 GameView 中。

标签: swiftswiftui

解决方案


希望这可以简化它

trunk注入,NavigationView不需要重新注入。即使其中一个孩子不使用它。卡车属于NavigationView

然后我创建了 2 个分支AB它们有自己的 ObjectsA看不到Bs 和反之亦然。

每个分支都可以访问它们的对象,并且子分支(NavigationLink)可以通过注入来连接到分支的对象。

import SwiftUI

struct TreeView: View {
    @StateObject var trunk: Trunk = Trunk()
    var body: some View {
        NavigationView{
            List{
                NavigationLink(
                    destination: BranchAView(),
                    label: {
                        Text("BranchA")
                    })
                NavigationLink(
                    destination: BranchBView(),
                    label: {
                        Text("BranchB")
                    })
                
            }.navigationTitle("Trunk")
        }
        //Available to all items in the NavigationView
        //With no need to re-inject for all items of the navView
        .environmentObject(trunk)
        
    }
}
///Has no access to BranchB
struct BranchAView: View {
    @StateObject var branchA: BranchA = BranchA()
    @EnvironmentObject var trunk: Trunk
    var body: some View {
        VStack{
            Text(trunk.title)
            Text(branchA.title)
            NavigationLink(
                destination: BranchAAView()
                    //Initial injection
                    .environmentObject(branchA)
                ,
                label: {
                    Text("Go to Branch AA")
                })
        }.navigationTitle("BranchA")
    }
}
//Has no access to BranchA
struct BranchBView: View {
    @StateObject var branchB: BranchB = BranchB()
    @EnvironmentObject var trunk: Trunk
    var body: some View {
        VStack{
            Text(trunk.title)
            Text(branchB.title)
            NavigationLink(
                destination: BranchBBView()
                    //Initial injection
                    .environmentObject(branchB),
                label: {
                    Text("Go to Branch BB")
                })
        }.navigationTitle("BranchB")
    }
}
struct BranchAAView: View {
    @EnvironmentObject var branchA: BranchA
    @EnvironmentObject var trunk: Trunk
    var body: some View {
        VStack{
            Text(trunk.title)
            Text(branchA.title)
            NavigationLink(
                destination: BranchAAAView()
                    //Needs re-injection because it is a NavigationLink sub-branch
                    .environmentObject(branchA)
                ,
                label: {
                    Text("Go to AAA")
                })
        }.navigationTitle("BranchAA")
    }
}
struct BranchAAAView: View {
    @EnvironmentObject var branchA: BranchA
    @EnvironmentObject var trunk: Trunk
    var body: some View {
        VStack{
            Text(trunk.title)
            Text(branchA.title)
        }.navigationTitle("BranchAAA")
    }
}
struct BranchBBView: View {
    var body: some View {
        VStack{
            Text("I don't need to use the trunk or branch BB")
            //No need to re-inject it is the same branch
            BranchBBBView()
        }.navigationTitle("BranchBB")
    }
}
struct BranchBBBView: View {
    @EnvironmentObject var branchB: BranchB
    @EnvironmentObject var trunk: Trunk
    var body: some View {
        VStack{
            Text("BranchBBBView").font(.title).fontWeight(.bold)
            Text(trunk.title)
            Text(branchB.title)
        }.navigationTitle("BranchBB & BranchBBB")
    }
}
struct TreeView_Previews: PreviewProvider {
    static var previews: some View {
        TreeView()
    }
}
class Trunk: ObservableObject {
    var title: String = "Trunk"
}
class BranchA: ObservableObject {
    var title: String = "BranchA"
}
class BranchB: ObservableObject {
    var title: String = "BranchB"
}

推荐阅读