NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

How can I append and remove variables from an array tagged with the @State property wrapper?

Forums > SwiftUI

I have a view that draws buttons, according to the state of an array of buttons. In that same strut, I have an add() method to add buttons to the array, which is giving me the following error: iew.swift:60: warning run: Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update.

Here’s the struct in question:

Struct rowOfButtons: View { @State var displayedButtons = [Button]()

Var body -> some View {

Stack { ForEach(buttons, id:.self) {newButton in newButton }//loop }//Hstack }//body

//methods

Mutating func add(newButton: Button) { Buttons.append(newButton) }//func }//struct

With that, when instantiating new RowOfButtons objects, I create the instance, then loop over values of buttons that need to be added to the view, like this: /Note: This is a simplified version of what I’m trying to do to make my post shorter. This would be inside some other View struct, and the returned array would be assigned to a property inside that struct /

Func initializeRowsWithButtons -> [RowsOfButtons] { Let buttonNames = [/some array of button names returned from another function/] //I also get an array that of integers that defines how many buttons will be in each row Let arrayOfRowSizes = [/some returned array of integers/]

//This is the return array Var filledRows = [RowOfButtons]() //gets incremented in the loop Var indexInButtonNames = 0 For I in arrayOfRowSizes {

Var newRow = RowOfButtons()

For _ in 0..<I {

/I’ve tried to ways to add to the array. Here’s the first: / newRow.add(Button(buttonNames[indexInButtonNames])

/This is the other way: newRow.displayedButtons.append(Button(buttonNames[indexInButtonNames])) / indexInButtonNames += 1 }//nested loop

filledRows.append(newRow) }//loop

Return filledRows }//func

Again, the add() method in the RowOfButtons astruct and the two attempts displayed in the above method throw the same error that I mentioned at the top of this post. I’m unsure of how else I can get around this. Does anyone have some suggestions?

   

Please edit your post and use code tags. It's very hard to read and differentiate between your explanation and your code.

1      

I'm completely-blind, and the text editor on this site isn't fully-accessible with Voiceover. Will comments like, "//begin code", and "//end code work to separate things for you visually?

   

Hi DarkhorseStudios,

I see you are trying to create a View that gives you rows of buttons with some names.

Below code shall work.

I also notice your were creating array of Buttons as @State. It would be easier if you put data in @State or @StateObject, and use that data to create view items in View's body. When I say data, I mean attributes that define your UI, just like the names you used.

I am not even using @State in my code below because I don't change the View after it is created. Use @State as you need.

import SwiftUI

struct RowOfButtons: View {
    var buttonNames: [String]

    var body: some View {
        List(buttonNames, id: \.self) { buttonName in
            Button(buttonName) {  }
        }
    }
}

struct RowOfButtons_Previews: PreviewProvider {
    static var previews: some View {
        RowOfButtons(buttonNames: ["Hacking", "With", "Swift"])
    }
}

For other folks, DarkhorseStudios's the original code would be close to:

struct RowOfButtons: View { 

    @State var displayedButtons = [Button]()

    var body -> some View {
        Stack { 
            ForEach(buttons, id:.self) {
                newButton in newButton 
            }//loop 
        }//Hstack 

    }//body

    //methods
    mutating func add(newButton: Button) { 
        displayedButtons.append(newButton) 
    }//func 

}//struct

func initializeRowsWithButtons -> [RowsOfButtons] { 
    let buttonNames = [/some array of button names returned from another function/] 
    //I also get an array that of integers that defines how many buttons will be in each row 
    let arrayOfRowSizes = [/some returned array of integers/]

    //This is the return array
    var filledRows = [RowOfButtons]() //gets incremented in the loop
    var indexInButtonNames = 0 

    for I in arrayOfRowSizes {
        var newRow = RowOfButtons()

        for _ in 0..<I {
            //I’ve tried to ways to add to the array. Here’s the first: 
            newRow.add(Button(buttonNames[indexInButtonNames])

            //This is the other way: 
            newRow.displayedButtons.append(Button(buttonNames[indexInButtonNames]))
            indexInButtonNames += 1
        } //nested loop

        filledRows.append(newRow) 
    }//loop

    Return filledRows 

}//func

1      

I'm not sure if you are typing with a keyboard or by voice commands, but just to possibly help you understand what somebody requested earlier in this thread...

You can wrap your code in triple backticks to make it show up as properly formatted code in these forums.

I'm not sure if backticks is the proper name for them that voice typing commands would understand, but it is the button just below the escape key on the mac keyboard.

I typically type three backticks, press return to move to a new line, then type three more backticks. Then I create a new line between the two lines of backticks and paste my code there.

I can't even imagine trying to do this completely blind. I often struggle with finding small errors in my code even though I can look to see them. That is quite impressive.

Best of luck to you.

1      

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.