SWIFTUI-如何导航到随机视图?

时间:2019-12-29 22:47:43

标签: arrays swiftui navigationlink

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

}

3 个答案:

答案 0 :(得分:2)

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

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

第一个解决方案

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

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

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

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

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

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

第二个解决方案:

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

玩得开心,
大卫

答案 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)

最后。
如果每个问题视图都以模态方式打开然后被解雇,那么您应该不会有任何性能或内存问题。