0

我已经构建了一个原始测验应用程序。有ContentView一个navigationlink问题。从问题一的观点来看(这是一个叫做 questionOne 的观点),我有一个问题和另一个navigationlink要 questionTwo 的观点。它一直持续到最后一个问题,在最后一个问题(有 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
     @State var isSelected = false

     func onClick() {
          counter += 1
          if counter == 1 { score += 1}
          else if counter > 1 { score += 0}
      }

      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
     @State var isSelected = false
     func onClick() {
          counter += 1
          if counter == 1 { score += 1}
          else if counter > 1 { score += 0}
     }

     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)
        }
}
4

2 回答 2

2

我将为您提供一些操作方法的解决方案。
实施细节将留给读者。

您不想创建 194 个 SwiftUI 视图(或 UIViewControllers)的堆栈。原因如下:
1. 创建一个仅显示 3 或 4 个问题的测试应用程序。
2. 在模拟器中运行它并转到您的最后一个问题。
3. 进入调试 | 查看调试 | 捕获视图层次结构。
4. 想象一下,对于 194 个问题的 Views。

第一个解决方案

  1. 创建一个对象数组,其中每个对象包含:
    a/ 字符串等以保存每个问题和答案以及任何其他问题信息。
    b/ questionHasBeenShown Bool 标志,用于指示问题是否已显示。

  2. 创建一个 showQuestionsCounter 来跟踪您显示了多少问题。

  3. 根据 questionHasBeenShown == false 过滤数组。
    (您可以尝试从原始数组中删除已查看的问题,而不是显示它们。然后您不需要 Bool。)

  4. 使用随机数选择下一个问题。
    增加计数器。

  5. 使用您刚刚选择的下一个问题来更新视图中的所有控件。

您只需为此使用一个视图,而不是为每个问题创建一个新视图。

第二种解决方案:

如果您坚持为每个问题
创建一个新视图...为下一个问题创建一个新视图,并使用与第一个解决方案相同的逻辑来填充新视图。

玩得开心,
大卫

于 2019-12-30T05:41:54.913 回答
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()

或者:

也许使用 QuestionViewItem 内部(或代替)的闭包将协议结构和项目折叠成一行。
或者使用带有第二项闭包的元组。
那会更迅速,也更酷。

于 2019-12-31T03:33:49.547 回答