【问题标题】:SWIFTUI - How to navigate to a random view?SWIFTUI - 如何导航到随机视图?
【发布时间】:2019-12-29 22:47:43
【问题描述】:

我已经构建了一个原始的测验应用程序。 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)
        }
}

【问题讨论】:

    标签: arrays swiftui navigationlink


    【解决方案1】:

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

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

    第一个解决方案

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

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

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

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

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

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

    第二种解决方案:

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

    玩得开心,
    大卫

    【讨论】:

    • 非常感谢您的详尽回答。由于我已经创建了所有视图(我接受,它非常原始),有没有办法将视图放在一个数组中并使用带有导航链接的数组?
    • 看我的下一个“答案”。 (我不知道如何让代码格式在评论中起作用。)
    【解决方案2】:

    我没有测试或编码以下任何...
    您可以尝试以下方法:

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

    【讨论】:

      猜你喜欢
      • 2020-06-03
      • 2021-08-09
      • 1970-01-01
      • 2021-02-20
      • 2021-04-06
      • 1970-01-01
      • 2019-11-23
      • 2020-01-10
      • 2020-07-26
      相关资源
      最近更新 更多