如何在 swiftui 中为子视图设置私有状态变量?

Posted

技术标签:

【中文标题】如何在 swiftui 中为子视图设置私有状态变量?【英文标题】:How do I have private state variables for a childview in swiftui? 【发布时间】:2021-11-01 15:57:02 【问题描述】:

所以我正在创建这个应用程序,用户可以在其中选择他希望练习的乘法表,以及第一个视图上的问题数量,然后按下按钮,

它会继续传递这些数据的下一个视图,然后它会创建一个问题库供他做

有一个错误说我不能传递一个私有变量,为什么会这样?我已附上我的代码以供参考

import SwiftUI


struct ContentView: View 
    
    @State private var multiplicationTable = 1
    @State private var amountQuestions = 1
  
    
    let multiplicationTables = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    let amountQuestionss = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    var body: some View 
        NavigationView 
            
            VStack 
                
                Picker(selection: $multiplicationTable, label: Text("multiplicationTable")) 
                    ForEach(0 ..< 10) num in
                        Text("\(multiplicationTables[num])")
                    
                
                .padding()
                .padding()
                Text("Choose number of Questions")
                Picker("Select number of questions", selection: $amountQuestions) 
                    ForEach(0 ..< 10) num in
                        Text("\(amountQuestionss[num])")
                    
                
                
                NavigationLink(destination: kek(One: multiplicationTable, Two: amountQuestions)  .navigationBarHidden(true)) 
                    Button ("GO") 
                       
                          
                        
                    
                    .padding(50)
                    .background(Color.red)
                    .foregroundColor(.white)
                    .clipShape(Circle())
                    
                
                .navigationTitle("Choose Multiplication Table")
                .navigationBarTitleDisplayMode(.inline)
                
              
                
            
            
        
    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        ContentView()
    

这是第一个视图,这是第二个视图

import SwiftUI

struct kek: View 
    
    let One : Int
    let Two : Int
    
    @State  var Question : String

    @State  var answer = ""
    @State  var Three = 0
    @State  var Four = 0
    
    
    func nextQuestion()
       Three = One
        Four = Int.random(in: 0...10)
        
        Question = "\(Three) * \(Four)"
        
    
    
    
    var body: some View 
        VStack 
            
            Text("Question: What is \(Question)?")
            Form 
                Section 
                    TextField("Amount", text: $answer)
                        .keyboardType(.decimalPad)
                    
                    
                
                
            
          
                Button ("Next") 
                   
                      
                    
                
                .padding(50)
                .background(Color.red)
                .foregroundColor(.white)
                .clipShape(Circle())
                
            
            
            
        
        
    




struct kek_Previews: PreviewProvider 
    static var previews: some View 
        kek(One: 1, Two: 2)
    

【问题讨论】:

我没有看到错误提示您“无法传递私有变量”。 错误提示您没有为kekQuestion 参数传递任何内容。顺便说一句,在 Swift 中,通常的做法是类型名称以大写字母开头,变量/属性名称以小写字母开头。这样做会让其他人也更容易阅读您的代码。 我试图让 Question 成为 kek 视图的本地变量。我通过使用@State private var Question 来做到这一点,但是 swiftui 给了我错误“由于'私有'保护级别而无法访问初始化程序”我相信 swiftui 认为 Question 变量是 kek 视图的参数。但我不希望它成为一个参数。我希望它通过 kek 视图在本地初始化我该怎么办 在kek中给它一个初始值——现在你还没有指定一个初始值 【参考方案1】:

我不确定您在哪里得到错误,因为可以将变量传递到另一个视图。我修改了您的代码以说明我认为您正在努力实现的目标。

struct ContentView: View 

@State private var multiplicationTable = 1
@State private var amountQuestions = 1

let multiplicationTables = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let numberOfQuestions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var body: some View 
    NavigationView 

        VStack 
            Picker("Multiplication Table", selection: $multiplicationTable) 
                // There was an "off by one" issue in the kek View which I resolved by using the value of the array itself for the selection. Not the location in the array.
                ForEach(multiplicationTables, id: \.self)  num in
                    Text("\(num)")
                
            
            .pickerStyle(.segmented)
            .padding([.top, .bottom], 20)
            /*
             Don't use
                .padding()
                .padding()
             Instead you can specify how large you'd like the padding to be around the view.
             */
            Text("Choose number of Questions")
            Picker("Select number of questions", selection: $amountQuestions) 
                ForEach(0 ..< numberOfQuestions.count) num in
                    Text("\(numberOfQuestions[num])")
                
            

            NavigationLink 
                kek(one: multiplicationTable, two: amountQuestions)
             label: 
                // A NavigationLink is clickable by default, so you don't need to place a button inside of it.
                // Here I used Text and formatted it just as you had with your Button.
                Text("Go")
                    .padding(50)
                    .background(Color.red)
                    .foregroundColor(.white)
                    .clipShape(Circle())
            
            .navigationTitle("Choose Multiplication Table")
            .navigationBarTitleDisplayMode(.inline)
        
    

struct kek: View 
    let one: Int
    let two: Int // note: It doesn't look like you're actually using this property. Consider removing it.


    @State private var answer = ""
    @State private var randomNumber = 0

    @State private var three = 0
    @State private var question = ""


    func nextQuestion()
        three = one
        randomNumber = Int.random(in: 0...10)

        question = "\(three) * \(randomNumber)"
    


    var body: some View 
        VStack 

            Text("Question: What is \(question)?")
            Form 
                Section 
                    TextField("Amount", text: $answer)
                         .keyboardType(.decimalPad)
                
            
            Button ("Next") 
                nextQuestion()
            
            .padding(50)
            .background(Color.red)
            .foregroundColor(.white)
            .clipShape(Circle())
        

    

【讨论】:

谢谢。我正在尝试使 Question 成为 kek 视图的本地变量。我通过使用@State private var Question 来做到这一点,但是 swiftui 给了我错误“由于'私有'保护级别而无法访问初始化程序”我相信 swiftui 认为 Question 变量是 kek 视图的参数。但我不希望它成为一个参数。我希望它通过 kek 视图在本地初始化我该怎么办 我明白了。如果您给 Question 一个初始值,例如一个空字符串,那么您将能够在 kek 视图中本地使用它。像这样:@State private var Question = "" 那仍然是一个字符串,它只是空的,但它已经在视图中初始化了。我相信这对您的目的有用。 我更新了我的答案以反映这些 cmets。

以上是关于如何在 swiftui 中为子视图设置私有状态变量?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI如何将列表项重构为子视图

如何在 VStack 中为子视图排列底部文本

在 SwiftUI 中为 UITextView 设置初始视图偏移量

SwiftUI - 在当前视图中为新图像设置动画

如何在swift / SwiftUI中为滑动手势设置菜单栏图标的操作

如何使用 SwiftUI 重置子视图状态变量?