程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了如何改变从其他视图传递过来的变量大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决如何改变从其他视图传递过来的变量?

开发过程中遇到如何改变从其他视图传递过来的变量的问题如何解决?下面主要结合日常开发的经验,给出你关于如何改变从其他视图传递过来的变量的解决方法建议,希望对你解决如何改变从其他视图传递过来的变量有所启发或帮助;

我是 SwiftUI 的新手,我尝试创建一个应用程序,它有一个目标列表,在列表上方,有一个添加按钮可以添加目标并将其显示在列表中。目前,我无法将目标实例添加到目标(目标数组)中,在创建视图中,我尝试将新的目标实例附加到我在另一个视图中创建的目标中。它给了我一条错误消息:Cannot use mutating member on immutable value: 'self' is immutable 在行 goals.append(Goal(...)) 上谁知道怎么修它?这是我的代码!非常感谢!

struct ContentVIEw: VIEw {
    var goals: [Goal] = []
    
    var body: some VIEw {
        TabVIEw{
            vstack{
                Text("You have")
                Text("0")
                Text("tasks to do")
            }.tabItem { Text("Home")}
            MyScroll(1..<100).tabItem { Text("My Goals") }
        }
    }
}

struct MyScroll: VIEw {
    var numRange: Range<Int>
    var goals: [Goal]
    
    init (_ r:Range<Int>) {
        numRange = r
        goals = []
    }
    
    var body: some VIEw {
        NavigationVIEw{
            vstack{
                Navigationlink(destination: AddVIEw(goals:self.goals)){
                    Image(systemname: "folder.badge.plus")
                }
                List(goals) { goal in
                    HStack(alignment: .center){
                        Text(goal.name)
                    }
                }
            }
        }.navigationTitle(Text("1111"))
    }
}

struct AddVIEw: VIEw {
    var goals:[Goal]
    @State var types = ["study","workout","hobby","habbit"]
    @State private var selected = false
    @State var selection = Set<String>()
    @State var goalname: String = ""
    @State var goalType: String = ""
    @State var isLongTerm: Bool = false
    @State var progress: [Progress] = []
    
    var body: some VIEw {
        vstack{
            Text("Create your goal")
            // type in name
            HStack{
                TextFIEld("name",text: $goalname)
            }.padding()
            // choose type: a selection List
            HStack{
                List(types,ID: \.self,selection: $selection) {
                    Text($0)
                }
                .navigationbarItems(trailing: Editbutton())
            }.padding()
            // toggle if it is a logn term goal
            HStack{
                Toggle(isOn: $selected) {
                    Text("Is your goal Long Term (no end date)")
                }.padding()
            }.padding()
            button(action: {
                addGoal(goalname,goalType,isLongTerm,progress)
            },label: {
                /*@START_MENU_TOKEN@*/Text("button")/*@END_MENU_TOKEN@*/
            })
        }
    }
        
    // function that add the goal instance to the goals
    mutating func addGoal( _ t:String,_ n:String,_ iLT: Bool,_ p: [Progress]){
        let item: Goal = Goal(t,n,iLT,[])
        goals.append(item)
    }
}

目标只是我为存储信息而创建的结构:

import Foundation

// This is the structure for each goal when it is created
struct Goal: IDentifiable {
    var ID: UUID
    var type: String // type of goals
    var name: String // the custom name of the goal
    var isLongTerm: Bool // if goal is a long term goal (no deadline)
    var progress: [Progress] // an array of progress for each day
    
    init(_ t:String,_ p: [Progress]) {
        ID = UUID()
        type = t
        name = n
        isLongTerm = iLT
        progress = p
    }
}

解决方法

实现此目的的一种方法是使用 @Binding 将 @State 保存在父视图中,并将其向下传递到视图层次结构,让子视图向上发送数据。

(一个警告是,在当前版本的 SwiftUI 中,通过多个视图发送 Binding 看起来可能会产生意想不到的结果,但一两个级别似乎没问题。另一种选择是使用带有 @Published 属性的 ObservableObject在视图之间传递)

注意 ContentView 如何拥有 [Goal],然后后续子视图将其作为 @Binding 获取——$ 符号用于通过参数:

struct Goal: Identifiable {
    var id: UUID
    var type: String // type of goals
    var name: String // the custom name of the goal
    var isLongTerm: Bool // if goal is a long term goal (no deadline)
    var progress: [Progress] // an array of progress for each day
    
    init(_ t:String,_ n:String,_ iLT: Bool,_ p: [Progress]) {
            id = UUID()
            type = t
            name = n
            isLongTerm = iLT
            progress = p
        }
}

struct ContentView: View {
    @State var goals: [Goal] = []

    var body: some View {
        TabView{
            VStack{
                Text("You have")
                Text("\(goals.count)")
                Text("tasks to do")
            }.tabItem { Text("Home")}
            MyScroll(numRange: 1..<100,goals: $goals).tabItem { Text("My Goals") }
        }
    }
}

struct MyScroll: View {
    var numRange: Range<Int>
    @Binding var goals: [Goal]
    
    var body: some View {
        NavigationView{
            VStack{
                NavigationLink(destination: AddView(goals:$goals)){
                    Image(systemName: "folder.badge.plus")
                }
                List(goals) { goal in
                    HStack(alignment: .center){
                        Text(goal.name)
                    }
                }
            }
        }.navigationTitle(Text("1111"))
    }
}

struct AddView: View {
    @Binding var goals:[Goal]
    @State var types = ["study","workout","hobby","habbit"]
    @State private var selected = false
    @State var selection = Set<String>()
    @State var goalName: String = ""
    @State var goalType: String = ""
    @State var isLongTerm: Bool = false
    @State var progress: [Progress] = []
    
    var body: some View {
        VStack{
            Text("Create your goal")
            // type in name
            HStack{
                TextField("Name",text: $goalName)
            }.padding()
            // choose type: a selection list
            HStack{
                List(types,id: \.self,selection: $selection) {
                    Text($0)
                }
                .navigationBarItems(trailing: EditButton())
            }.padding()
            // toggle if it is a logn term goal
            HStack{
                Toggle(isOn: $selected) {
                    Text("Is your goal Long Term (no end date)")
                }.padding()
            }.padding()
            Button(action: {
                addGoal(goalType,goalName,isLongTerm,progress)
            },label: {
                /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
            })
        }
    }
        
    // function that add the goal instance to the goals
    func addGoal( _ t:String,_ p: [Progress]){
        let item: Goal = Goal(t,n,iLT,[])
        goals.append(item)
    }
}

您的 addGoal 函数不再需要改变,因为它实际上不再改变自己的状态(无论如何这在 SwiftUI 中不起作用)。

作为旁注,我会谨慎地编写您的初始化程序和函数,就像您对 _ 未命名参数所做的那样——我在您的原始代码中找到了一个您打算传递名称的地方目标,而是传递该参数的类型,并且由于所有参数都未命名,因此没有警告。

大佬总结

以上是大佬教程为你收集整理的如何改变从其他视图传递过来的变量全部内容,希望文章能够帮你解决如何改变从其他视图传递过来的变量所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: