为 swiftui 引用一个 json 数组文件

Referring to a json array file for swiftui

我正在尝试编写代码,以便每次单击确认答案按钮时,都会调用 json 数组中的下一个问题。这个文件中有五个问题,到目前为止我可以让第一和第二个问题出现。无论如何我可以写一个循环,以便每次用户输入确认时调用下一个问题? 我是 swiftui 的新手,所以不确定如何进行

import SwiftUI
struct SecondView: View {

var ResearchMCQ: Question


//Creating Variables for Revision Topics
@State private var setOptionOne = false
@State private var setOptionTwo = false
@State private var setOptionThree = false
    
let button = ["Confirm Answer"]
@State public var buttonConfirm: Int?

        var body: some View {

        ScrollView{
            
            VStack(spacing: 1.0) {
   
 Group {
    Text(ResearchMCQ.question)
    .padding(.trailing, 5)
    

//Ensures Only One Answer Can Be Selected
        let OptionOne = Binding<Bool>(get: { self.setOptionOne }, set: { self.setOptionOne = [=11=]; self.setOptionTwo = false; self.setOptionThree = false })
        let OptionTwo = Binding<Bool>(get: { self.setOptionTwo }, set: { self.setOptionOne = false; self.setOptionTwo = [=11=]; self.setOptionThree = false })
        let OptionThree = Binding<Bool>(get: { self.setOptionThree }, set: { self.setOptionOne = false; self.setOptionTwo = false; self.setOptionThree = [=11=] })


        VStack {
            Toggle(ResearchMCQ.options[0], isOn: OptionOne)
                .toggleStyle(.button)
                .tint(Color(.gray))
                .foregroundColor(Color("Black-White"))
            Toggle(ResearchMCQ.options[1], isOn: OptionTwo)
                .toggleStyle(.button)
                .tint(Color(.gray))
                .foregroundColor(Color("Black-White"))
            Toggle(ResearchMCQ.options[2], isOn: OptionThree)
                .toggleStyle(.button)
                .tint(Color(.gray))
                .foregroundColor(Color("Black-White"))
                 }
    }
                
                Spacer()
                Spacer()
                
                HStack(spacing: 15) {
                ForEach(0..<button.count, id: \.self) {button in
                        Button(action: {
                            self.buttonConfirm = button
                            
                        }) {
                            
    //Links Continue Button To Next Page
                            NavigationLink(destination: SecondView(ResearchMCQ: questions[1])) {
                                Text("Confirm Answer")
                                
                            }
                            
                            .padding(.vertical, 12.5)
                            .padding(.horizontal, 120)
                            .foregroundColor(.white)
                            .foregroundStyle(.background)
                            .background(2 == button ? Color.primary: Color.secondary)
                            .clipShape(Capsule())
                    
                    
                }
                
                
        }
    }
}
            

   .navigationTitle("")
            
        }

}

        }


struct SecondView_Previews: PreviewProvider {
static var previews: some View {
    SecondView(ResearchMCQ: questions[0])

}

}

你可以用一个@Statevar来记住你问题的活跃指数,然后把这个指数加起来就行了。这样做就不需要进一步的意见了。

通常您会从父视图中计算问题,然后让子视图显示一个问题(和答案)。

struct Question: Identifiable {
    let id = UUID()
    var question: String
    var options: [String] =  ["One", "Two", "Three"]
}

struct ContentView: View {
    
    // dummy data
    let researchMCQ: [Question] = [
        Question(question: "First Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
        Question(question: "Second Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
        Question(question: "Third Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui"),
        Question(question: "Fourth Question: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa qui")
    ]
    
    // currently active question index
    @State private var activeQuestionIndex = 0
    
    //picked Option/Answer
    @State private var pickedOption = 0
    
    
    var body: some View {
        
        VStack(spacing: 1.0) {
            
            Group {
                Text(researchMCQ[activeQuestionIndex].question)
                    .padding(.bottom)
                
                Picker("Select Answer", selection: $pickedOption) {
                    Text(researchMCQ[activeQuestionIndex].options[0]).tag(0)
                    Text(researchMCQ[activeQuestionIndex].options[1]).tag(1)
                    Text(researchMCQ[activeQuestionIndex].options[2]).tag(2)
                }
                .pickerStyle(.segmented)
            }
            
            Spacer()
            
            Button(action: {
                if activeQuestionIndex < researchMCQ.count-1 {
                    self.activeQuestionIndex += 1
                    self.pickedOption = 0
                }
            }) {
                Text("Confirm Answer")
            }
            .padding(.vertical, 12.5)
            .padding(.horizontal, 120)
            .foregroundColor(.white)
            .foregroundStyle(.background)
            .background(Color.primary)
            .clipShape(Capsule())
            
        }
        .padding()
    }
}

如果所有问题的结构都相似,则有几种方法可以实现。

例如,在父视图中,您可以遍历问题数组并每次 SecondView 调用一个不同的问题。我推荐这种方法。

因为你没有提供父视图代码,所以我在下面提出一种直接遍历数组的方法SecondView

您可以更改同一视图,而不是导航到另一个视图。因此,SecondView 应该包含 所有 个问题,而不仅仅是一个问题,并且您可以更改所显示问题的索引。

要遵循的步骤如下:

  1. 让您的观点涵盖所有问题,而不仅仅是一个问题。顺便说一下,在 Swift 中变量是小写字母。
// Remember to pass the whole array of questions to this variable
let researchMCQ: [Question]
  1. 有另一个变量来保存当前问题。
@State private var questionIndex = 0
  1. 另外 buttonConfirm 在这种情况下应该是一个数组。
@State public var buttonConfirm = [Int?]()
  1. 显示当前问题(查看这里如何使用变量researchMCQ)。
 Group {
    Text(researchMCQ[questionIndex].question)
    .padding(.trailing, 5)
  1. 确认按钮不需要NavigationLink,只需更改索引即可显示下一个问题。
Button {
    buttonConfirm.append(button)
    // or this, if you initialize the var with the whole array:
    // buttonConfirm[questionIndex] = button

    // Make sure the index doesn't go beyond the array size
    if researchMCQ.count > questionIndex + 1 {
        questionIndex += 1
    }
} label: {
    Text("Confirm Answer")
}