我已经构建了一个原始的测验应用程序。 ContentView具有指向问题一的导航链接。在问题一的观点(这是一个名为问题一的观点)中,我有问题和到问题二的另一个导航链接。它一直持续到最后一个问题,最后一个问题(有194个问题)中都有指向结果视图的导航链接。因为所有内容都是这样硬编码的,所以问题的顺序总是相同的。
我想知道的是,我该如何随机分配194个问题的顺序,并在回答完每个问题后转到最后的结果视图。
由于我的有限知识,我应该创建一个视图数组并在导航链接中使用该数组,但是我不知道如何实现它。而且即使我可以实施它,我也不知道如何一次坐不出两次相同的问题,最后到达结果页面。
以下是我的代码示例:
这是主页:
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Text("Capitals of the World Trivia").font(.title)
.fontWeight(.bold)
NavigationLink(destination: questionOne()) {
logoView()
} .buttonStyle(PlainButtonStyle()).padding()
Text("Tap the globe to continue")
}
}
}
}
这是一个问题视图:
var score = 0
// I have a global variable for score,
struct questionOne: View {
@State var counter = 0
func onClick() {
counter += 1
if counter == 1 { score += 1}
else if counter > 1 { score += 0}
}
@State var isSelected = false
var body: some View {
GeometryReader { GeometryProxy in
VStack (alignment: .center){
Q1Prague().cornerRadius(10)
Spacer()
Text(verbatim: "What's the capital of Czech Republic?")
.font(.title)
.frame(width: 350, height: 80)
Button(action: {self.isSelected.toggle()}) {
Text("Novigrad")
}.buttonStyle(SelectedButtonStyleFalse(isSelected: self.$isSelected))
Spacer()
Button(action: {self.onClick();self.isSelected.toggle()}) {
Text("Prague")
}.buttonStyle(SelectedButtonStyle(isSelected: self.$isSelected))
Spacer()
Button(action: {self.isSelected.toggle()}) {
Text("Ostrava")
} .buttonStyle(SelectedButtonStyleFalse(isSelected: self.$isSelected))
Spacer()
VStack {
HStack { NavigationLink(destination: questionTwo()) {
Text("Next Question")
}
}
AdView().frame(width: 150, height: 60)
}
}
}.padding(.top, 80).edgesIgnoringSafeArea(.top)
}
}
这是我的最后一个问题:
struct question194: View {
@State var counter = 0
func onClick() {
counter += 1
if counter == 1 { score += 1}
else if counter > 1 { score += 0}
}
@State var isSelected = false
var body: some View {
GeometryReader { GeometryProxy in
VStack (alignment: .center) {
Q194Athens().cornerRadius(10)
Spacer()
Text(verbatim: "What's the capital of Greece?")
.font(.title)
.frame(width: 400, height: 80)
Button(action: {self.onClick();self.isSelected.toggle()}) {
Text("Athens")
}.buttonStyle(SelectedButtonStyle(isSelected: self.$isSelected))
Spacer()
Button(action: {self.isSelected.toggle()}) {
Text("Sparta")
}.buttonStyle(SelectedButtonStyleFalse(isSelected: self.$isSelected))
Spacer()
Button(action: {self.isSelected.toggle()}) {
Text("Ostrava")
} .buttonStyle(SelectedButtonStyleFalse(isSelected: self.$isSelected))
Spacer()
VStack {
HStack { NavigationLink(destination: ResultPage()) {
Text("Next Question")
}
}
AdView().frame(width: 150, height: 60)
}
}
}.padding(.top, 80).edgesIgnoringSafeArea(.top)
}
}
答案 0 :(得分:2)
我将为您提供一些解决方法。
实现细节将留给读者。
您不想创建194个SwiftUI视图(或UIViewControllers)的堆栈。
原因如下:
1.创建一个仅显示3或4个问题的测试应用。
2.在模拟器中运行它,然后转到最后一个问题。
3.转到调试|查看调试|捕获视图层次结构。
4.想象一下,对于194个问题视图。
第一个解决方案:
创建一个对象数组,其中每个对象都包含:
a /字符串等,用于保存每个问题和答案以及任何其他问题的信息。
b /一个questionHasBeenShown Bool标志,用于指示该问题是否已显示。
创建一个showQuestionsCounter来跟踪您显示了多少个问题。
根据questionHasBeenShown == false过滤数组。
(您可以尝试从显示的原始数组中删除已查看的问题,而不是如图所示。然后,您就不需要Bool。)
使用随机数选择下一个问题。
递增计数器。
使用刚刚选择的下一个问题来更新视图中的所有控件。
您只能为此使用一个视图,而不会为每个问题创建一个新视图。
第二个解决方案:
如果您坚持要对每个问题使用新视图...
为下一个问题创建一个新视图,并使用与第一个解决方案相同的逻辑来填充新视图。
玩得开心,
大卫
答案 1 :(得分:0)
我尚未测试或编码以下任何内容...
您可以尝试以下操作:
struct QuestionViewItem {
var wasShown: Bool
let questionView: View
}
var questionArray[QuestionViewItem] = [
{ false, QuestionView1() },
{ false, QuestionView2() },
{ false, QuestionView3() },
...
]
如果因为要创建所有194个视图而永久创建它 初始化后,您可以尝试使用协议...
protocol QuestionViewProtocol {
func getQuestion() -> View
}
struct QuestionProtocolView1: QuestionViewProtocol {
func getQuestion() -> View {
return QuestionView1()
}
}
struct QuestionProtocolView2: QuestionViewProtocol {
func getQuestion() -> View {
return QuestionView2()
}
}
然后:
struct QuestionViewProtocolItem {
var wasShown: Bool
let questionViewProtocol: QuestionViewProtocol
}
var questionArray[QuestionViewProtocolItem] = [
{ false, QuestionProtocolView1() },
{ false, QuestionProtocolView2() },
{ false, QuestionProtocolView3() },
...
]
并创建每个视图:
questionArray[n].questionViewProtocol.getQuestion()
OR:
也许可以使用QuestionViewItem内部(或替代其内部)的闭包将协议结构和项目折叠到一行中。
或者将元组与第二个项目一起使用。
那会更迅速,更酷。
答案 2 :(得分:0)
最后。
如果每个问题视图都以模态方式打开然后被解雇,那么您应该不会有任何性能或内存问题。