I'm having an issue grabbing the state out of an array of SwiftUI structs.
I have a struct for cards that contain topText and bottomText. I have another struct that is a form for input components such as the card. I store these cards in an array, appending more and more as a + button is clicked. In the parent view I have a foreach over that array so they render dynamically.
I'm having an issue with trying to extract the state value from these structs. The cards contain state for the topText and bottomText. When a save button is clicked in the parent array (where the array of cards exists), it iterates over the array of cards, and prints their state through a get method. However, it is not printing the current state of those cards. It prints a blank string. I believe this is happening because when I append the struct, it's merely copying a dead struct, and not the real stateful struct.
Do I have my assumptions correct? Or is this a bug in swiftUI? Does anyone have any ideas on a proper way to do this? I just want to get the input out of the cards whenever the button is clicked. It needs to be dynamic though, as the user can click the + button however many times they want and continue making more cards.
Heres the code for the card stuct:
struct memeCard: View, Identifiable{
@State private var topText = ""
@State private var bottomText = ""
let id = UUID()
// TODO: figure out how to make text wrap so it doesn't go on one line forever.
var body: some View{
VStack(spacing: 30){
TextField("Top text...", text: $topText).multilineTextAlignment(.center)
Divider()
TextField("Bottom text...", text: $bottomText)
}
.frame(width: 300, height: 350, alignment: .center).multilineTextAlignment(.center)
.background(Color.white)
.cornerRadius(20)
.shadow(color: Color.gray, radius: 4, x: 4, y: 4)
}
func getBottomText() -> String{
return self.bottomText
}
func getTopText() -> String{
return self.topText
}
}
And here is the parent view:
struct CreateMemePage: View {
@Environment(\.presentationMode) var presentation
let realm = try! Realm()
@State private var sectionInput = ""
@State private var memeTitleInput = ""
@State private var offsetValue: CGFloat = 0.0
@State private var createCards: [memeCard] = [memeCard()]
var body: some View {
NavigationView{
VStack(spacing: 30){
ScrollView{
TextField("Section...", text: $sectionInput)
.multilineTextAlignment(.center)
.frame(width: 350, height: 75, alignment: .center)
.background(Color.white)
.cornerRadius(15)
.shadow(color: Color.gray, radius: 4, x: 4, y: 4)
TextField("Meme Title...", text: $memeTitleInput)
.multilineTextAlignment(.center)
.frame(width: 350, height: 75, alignment: .center)
.background(Color.white)
.cornerRadius(15)
.shadow(color: Color.gray, radius: 4, x: 4, y: 4)
ForEach(0..<self.createCards.count, id: \.self){ item in
self.createCards[item].padding()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
}
Button(action: {
self.createCards.append(memeCard())
}) {
Image(systemName: "plus")
.accentColor(Color.white)
.frame(width: 50, height: 50, alignment: .center)
.background(LinearGradient(gradient: Gradient(colors: [ .red, .purple]), startPoint: .top, endPoint: .trailing))
.cornerRadius(60)
.shadow(color: Color.gray, radius: 2, x: 3, y: 3)
}
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.keyboardSensible($offsetValue)
.navigationBarTitle("Create meme")
.navigationBarItems(trailing:
Button(action: {
for item in createCards{
print(item.getBottomText())
print(item.getTopText())
}
}){
Text("Save")
}
) }
}
}