I have been looking on StackOverFlow (and on Internet) the entire day to make this button works but I haven't found anything.
As you can see, I want to change the value when I click on the button by using the simplest solution possible.
Here are the codes :
// Element.swift
import Foundation
import SwiftUI
struct Element: Identifiable {
let id = UUID()
@State var value: Double
let title: String
}
let elements = [
Element(value: 10, title: "This is a title"),
Element(value: 100, title: "This is another title")
]
// ElementView.swift
import SwiftUI
struct ElementView: View {
let element: Element
var body: some View {
HStack {
Text(element.title)
Text("\(element.value)")
Button("More", action: { element.value = 10 })
}
}
}
struct ElementView_Previews: PreviewProvider {
static var previews: some View {
ElementView(element: elements[0])
}
}
// ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
ForEach(elements) { element in
ElementView(element: element)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Surprisingly, I don't have any issue with Xcode.
What did I miss? Thanks in advance! :P
CodePudding user response:
You have a couple of issues with how you're treating state. In general, in SwiftUI, state is held by a parent and passed down to a child via Binding. It's also very important that @State
is for use inside a View
-- not inside your model.
See inline comments for changes and explanations.
struct Element: Identifiable {
let id = UUID()
var value: Double //Remove @State here -- @State is for use in a View
let title: String
}
struct ElementView: View {
@Binding var element: Element //pass Element via Binding so it is mutable
var body: some View {
HStack {
Text(element.title)
Text("\(element.value)")
Button("More", action: { element.value = 10 })
}
}
}
struct ElementView_Previews: PreviewProvider {
static var previews: some View {
ElementView(element: .constant(Element(value: 10, title: "This is a title"))) //use .constant() for a Binding in a Preview
}
}
struct ContentView: View {
@State private var elements = [ //define elements with @State so they are mutable
Element(value: 10, title: "This is a title"),
Element(value: 100, title: "This is another title")
]
var body: some View {
VStack {
ForEach($elements) { $element in //use element binding syntax to get a binding to each item in the array
ElementView(element: $element)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}