Swift 如何变异从其他视图传递的变量
我是SwiftUI新手,我尝试创建一个应用程序,它有一个目标列表,在列表上方,有一个添加按钮来添加目标并将其显示在列表上。目前,我在将目标实例添加到目标(目标数组)中遇到问题,在“创建”视图中,我尝试将新的目标实例附加到我在另一个视图中创建的目标中。它给了我一条错误消息:不能在不可变值上使用mutating member:“self”在goals.append(Goal(…)行上是不可变的?这是我的密码!非常感谢你Swift 如何变异从其他视图传递的变量,swift,swiftui,Swift,Swiftui,我是SwiftUI新手,我尝试创建一个应用程序,它有一个目标列表,在列表上方,有一个添加按钮来添加目标并将其显示在列表上。目前,我在将目标实例添加到目标(目标数组)中遇到问题,在“创建”视图中,我尝试将新的目标实例附加到我在另一个视图中创建的目标中。它给了我一条错误消息:不能在不可变值上使用mutating member:“self”在goals.append(Goal(…)行上是不可变的?这是我的密码!非常感谢你 struct ContentView: View { var goals
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)
}
}
一种方法是使用
@Binding
将@State保存在父视图中,并将其向下传递到视图层次结构中,让子视图将数据发送回
(一个警告是,在当前版本的SwiftUI中,通过多个视图发送绑定可能会产生意外的结果,但一个或两个级别似乎可以。另一个选项是使用带有@Published属性的ObserveObject,该属性在视图之间传递)
请注意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, _ n:String, _ iLT: Bool, _ p: [Progress]){
let item: Goal = Goal(t,n,iLT,[])
goals.append(item)
}
}
struct目标:可识别{
变量id:UUID
变量类型:字符串//目标类型
var name:String//目标的自定义名称
var isLongTerm:Bool//如果目标是长期目标(无最后期限)
var progress:[进度]//每天的进度数组
init(ut:String,n:String,iLT:Bool,p:[进度]){
id=UUID()
类型=t
name=n
isLongTerm=iLT
进度=p
}
}
结构ContentView:View{
@状态变量目标:[目标]=[]
var body:一些观点{
TabView{
VStack{
文本(“您有”)
文本(“\(goals.count)”)
文本(“要做的任务”)
}.tabItem{Text(“Home”)}
MyScroll(numRange:1..你需要@State-@State var goals:[Goal]=[]
你能显示目标类型的代码吗?我想你忘了给我们显示它了。我尝试添加@State,但它不起作用,我刚刚更新了GoalThank u的代码。这是一个非常有用和仔细的解释!
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, _ n:String, _ iLT: Bool, _ p: [Progress]){
let item: Goal = Goal(t,n,iLT,[])
goals.append(item)
}
}