我正在努力理解SwiftUI,并准备一个简单的应用程序来帮助我学习。我的应用程序有一个模型和两个视图,如下所示。
第一个问题很具体:;"更新锦标赛";去上班?我不知道我应该绑定哪个变量(如果有的话(,也不知道这是否是正确的方法。
struct Tournament { // eventually will have more properties, such as Bool, Date, arrays, etc.
var name: String
var location: String = "Franchises"
#if DEBUG
var tournamentData = [
Tournament(name: "Season Opener"),
Tournament(name: "May Day Tournament"),
Tournament(name: "Memorial Day Tournament"),
Tournament(name: "School's Out Tournament")
]
#endif
}
struct TournamentListView: View {
// should I use a different property wrapper if this is going to be something I refer to throughout the app?
@State var tournaments = tournamentData
var body: some View {
NavigationView {
VStack {
List(tournaments, id: .name) { tournament in
NavigationLink(
destination: TournamentDetailView(tournaments: $tournaments, tournament: tournament),
label: { Text (tournament.name)}
)
}
Spacer()
NavigationLink(
destination: TournamentDetailView(tournaments: $tournaments, addingNewTournament: true),
label: { Text ("Add a new tournament") }
)
}.navigationTitle("Tournaments")
}
}
}
struct TournamentDetailView: View {
@Environment(.presentationMode) var presentationMode
@Binding var tournaments: [Tournament]
@State var tournament = Tournament(name: "")
var addingNewTournament: Bool = false
var body: some View {
Form {
Section(header: Text("Tournament Info")) {
TextField("Name", text: $tournament.name)
TextField("Location", text: $tournament.location)
}
Section {
Button(action: {
if addingNewTournament { tournaments.append(tournament) }
presentationMode.wrappedValue.dismiss()
}) { Text(addingNewTournament ? "Create Tournament" : "Update Tournament") }
}
}
}
}
(附言:我删除了第二个问题,即我的代码是否或多或少很好,或者我是否没有做"SwiftUI方式",因为我的问题已经结束("这将帮助其他人回答问题"我的左脚!(。SO的另一个例子是我行我素,成为人们学习的障碍,而不是永远的工具。我问了一个非常具体的问题,但我也借此机会问我的做法是否合理。这不应该是管理员监管的事情,尤其是因为,我得到的一个回复实际上回答了一个我没有问过但想过的问题,即关于预览的问题。所以,让我直截了当地说:我只能问一个问题,否则我会被制裁,但人们可以回答比被问到的更多的;他们只需要有洞察力。太疯狂了。我认为我得到的回复体现了SO人帮助他人,甚至付出额外努力的优点。我的第二个问题显然更为笼统,不会让任何读过我问题的人感到困惑。(
首先,您应该记住,您只有一个真理来源来驱动整个应用程序。这个真理的来源将作为EnvironmentObject
传递。所以你所有的tournamentData
都将在这个类中。例如:
final class DataStore : ObservableObject{
#if DEBUG
@Published var tournamentData = [
Tournament(name: "Season Opener"),
Tournament(name: "May Day Tournament"),
Tournament(name: "Memorial Day Tournament"),
Tournament(name: "School's Out Tournament")
]
#else
@Published var tournamentData = [Tournament]()
#endif
}
这应该从您的顶级视图中传递。
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(DataStore())
}
}
只需从您的每个孩子的视图中访问即可。
@EnvironmentObject var store : DataStore
然后你应该更新这个单一的真相来源和里面的tournamentData
。一切都应该按预期进行。
我建议看苹果的WWDC SwiftUI视频。他们解释得很好。或者,如果你想先掌握更多的方法,请阅读本教程。太神奇了。
编辑:为了完整起见,我认为我还应该添加处理仅DEBUG
代码的正确方法。以上内容将起作用,但您真正应该做的是为PreviewProvider
内部的调试分配模型。无论如何,苹果都会将其从生产代码中删除。
所以在你的View
:里面
struct Listing_Previews: PreviewProvider {
static var previews: some View {
let store = DataStore()
store.tournamentData = [
Tournament(name: "Season Opener"),
Tournament(name: "May Day Tournament"),
Tournament(name: "Memorial Day Tournament"),
Tournament(name: "School's Out Tournament")
]
return Listing().environmentObject(store)
}
}
并从DataStore
中删除#if DEBUG