How to call a SwiftUI button by its UUID?

I am a beginner in SwiftUI.

For a memory game I created several buttons. I need to call each button individually to change its attributes. I can read out each button's UUID but I don't how to use the ID to call the button.

In good ol' HyperTalk I would write for example:

Code Block
set the style of card button <ID> to "shadow"


How can I do it in SwiftUI?

I need to call each button individually to change its attributes.

You should not try to identify a View (including Button) with UUID (or any other ids).
Declare an Array of attributes and make buttons to represent the attributes.
Can you give me a short example, please?

Can you give me a short example, please?

If you could have shown me your example code, I would do it.
That can be a pseudo code, meaning some parts of which do not compile.
I am not sure whether I expressed the problem clear enough. I need to change the attributes of the buttons from any place in my code; from "far away" so to say. I know that I can set the attributes of texts or buttons by e.g.
Code Block
.background(Color.green)

but I these attributes are always right below those elements. What I need is to set an attribute of a button or whatever when I click on another button (let's say a "reset button"). When I do it with a
Code Block
@State private var

then I change it for all at the same time but I need to call each button separately.

Look at this code (it is not the real program but only an example):

Code Block
 var body: some View {
        VStack {
        Text("This is Text 1")
            .foregroundColor(Color.green)
       Button(action: {
print("Blabla")
          }, label: {
            Image(systemName: "sunset")
                .font(.system(size: 100))
.background(Color.blue)
})
  .disabled(false)
        
 // This button shall change the color and the ".disable" of the button above and the color of the text, too.
        Button(action: {
        // Code to change the attributes goes here but what is it?
        }, label: {
            Text("Reset")
        })
}
}


I am afraid that I can solve this dilemma only with several
Code Block
@State private var

and have to write as many subprograms as I need buttons instead to write a
Code Block
var body: some View {
HStack {
prototypeButton(Text: "Button 1")
prototypeButton(Text: "Button 2")
}
}
struct prototypeButton: View {
var body: some View {
Button(action: {},
label: {
Text("Button")
}
}


Thanks for showing the code.
You said I can read out each button's UUID, but I cannot find any parts to read out each button's UUID?
One more, you wrote I created several buttons, but there is only one button of which the attributes should be modified.

I need to change the attributes of the buttons from any place in my code; from "far away" so to say.

Please include all the needed thing in the opening post, when you just say it does not work, we readers would spend plenty of time to find what's missing.

I think I could understand what you intend far better than nothing, but not enough to write an example.
Can you show a little bit better example which includes the codes:
  • to read out each button's UUID

  • several buttons

  • and the far away place where the attributes should be able to changed

(Is it in the same View, or somewhere in another View? When you say another View, please show the view hierarchy including the two (or more?) Views.)


I can read out the UUID with this:

Code Block
var buttonID = ""


And later in the code of the struct of the button (see my posting before):

Code Block
var ID = UUID()

But what now? I have the UUID but no possibility to call the button with this ID.

What I mean with "far away" is that the buttons are drawn at the beginning of the program, then comes much code and somewhere at the bottom of the code is a routine which shall change the attributes of the button at the beginning of the code. I gave you an example above. Imagine an electrical switch which is mounted somewhere in the room and it controls a lamp at the other side of the room. I don't know how I can express it more clearly.

Everything is in the same view, by the way.

But what now?

You said you have several buttons and you can read each button's UUID. So, seeing how you organized the UUIDs would help writing an example.

Everything is in the same view, by the way.

Thanks, that can be a good clue.


By the way, in the added part, the prototypeButton (in Swift, type names should start with Capital letter) does not have background nor disabled. And I cannot find another button to change the attributes in the body. (Please include the name of the view.)
I first thought I could have understood what you had intended, but now all such things are confusing me.

Please remember, we readers know nothing about your memory game, nothing about the design of the game, nothing in your mind.
If you make some inconsistent explanations, we are just confused and get hard to show something sure.

Can you show a little bit better example?


This is the whole code. It's not secret but only an exercise for me. It is not finished yet because I am stuck.

I did not know that this problem was so difficult. I have several buttons (it could also be texts) and want to change their attributes from another place of my code, e.g. a reset button. Look at the code. The reset button is the button "Mischen". I have to cut this post into halves because it exceeds the character limit.

Code Block
import SwiftUI
var farbe = Color.accentColor
// The Array for the symbols of the buttons
var bilder = ["moon", "moon", "house", "house", "sunset", "sunset", "cloud", "cloud"]
var arrayAuswahl = 0
var anzahl = 0
var bildAuswahl = ""
var rateBild1 = ""
var rateBild2 = ""
var index = 0
var sperrung = 0
var knopfIDallgemein = ""
var knopfID1 = ""
struct ContentView: View {
    // Placeholder variables before the real symbols are written to the buttons
    @State private var knopf1 = "questionmark"
    @State private var knopf2 = "questionmark"
    @State private var knopf3 = "questionmark"
    @State private var knopf4 = "questionmark"
    @State private var knopf5 = "questionmark"
    @State private var knopf6 = "questionmark"
    @State private var knopf7 = "questionmark"
    @State private var knopf8 = "questionmark"
    
    @State private var abdeckFarbe = Color.blue
    
    /// Start. Only for testing. Maybe obsolete later
    @State private var knopfSperren =  false
    /// End
    
    var body: some View {
        VStack {
            Spacer()
            // First row
            HStack {
               // The struct "Taste" below is called several times to draw the buttons.
                Taste(symbol: knopf1)
                    .background(abdeckFarbe)
                Taste(symbol: knopf2)
                    .background(abdeckFarbe)
                Taste(symbol: knopf3)
                    .background(abdeckFarbe)
                Taste(symbol: knopf4)
                    .background(abdeckFarbe)
            }
          
            // Second row
            HStack {
                Taste(symbol: knopf5)
                    .background(abdeckFarbe)
                Taste(symbol: knopf6)
                    .background(abdeckFarbe)
                Taste(symbol: knopf7)
                    .background(abdeckFarbe)
                Taste(symbol: knopf8)
                    .background(abdeckFarbe)
            }
            Spacer()
            // The cards are mixed.
            Button(action: {
                // Initialising the routine to re-mix the card with every tap on this button.
                knopf1 = "questionmark"
                knopf2 = "questionmark"
                knopf3 = "questionmark"
                knopf4 = "questionmark"
                knopf5 = "questionmark"
                knopf6 = "questionmark"
                knopf7 = "questionmark"
                knopf8 = "questionmark"
                bilder = ["moon", "moon", "house", "house", "sunset", "sunset", "cloud", "cloud"]
                abdeckFarbe = Color.orange
               // The number of elements in the array "bilder" is read.
                anzahl = bilder.count
      
                // The subroutine is executed as long as there are still elements in the array.
                if anzahl > 0 {
              // The loop is executed as long as there are buttons.
                    for maxAnzahlKnoepfe in 0...7 {
                        
                        // Pick a random symbol name from the array.
                        arrayAuswahl = Int.random(in: 0...anzahl-1)
                        
                        // The name of the element is written to the variable "bildAuswahl"
                        bildAuswahl = bilder[arrayAuswahl]
                        
                        // The picked element is removed from the array to prevent that it is picked again.
                        bilder.remove(at: arrayAuswahl)
                    anzahl = bilder.count
                        
                        // Depending on the counter "maxAnzahlKnoepfe" the corresponding button gets a symbol.
                        if maxAnzahlKnoepfe == 0 {
                            knopf1 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 1 {
                            knopf2 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 2 {
                            knopf3 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 3 {
                            knopf4 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 4 {
                            knopf5 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 5 {
                            knopf6 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 6 {
                            knopf7 = bildAuswahl}
                        else if maxAnzahlKnoepfe == 7 {
                            knopf8 = bildAuswahl}
                    }
                }
            }, label: {
                Text("Mischen")
            })
        }
    }
}

Code Block
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
// This struct defines the standard look of the buttons. It is a kind of prototype button.
struct Taste: View {
    
    var ID = UUID()
    
    // Maybe obsolete
    @State private var knopfGedrueckt = false
@State private var knopfGesperrt = false
    
    // Defines the symbol of the button
    var symbol: String
    
    // Defines the initial color of the button
    @State private var abdeckFarbe = Color.blue
    
 // The symbols are compared.
    func Vergleich() {
        // The index defines whether the first or the second button was tapped
        if index == 0 {
            rateBild1 = symbol
            index = 1
        } else if index == 1 {
            rateBild2 = symbol
            index = 2
        }
        
        if index == 2 && rateBild1 == rateBild2 {
            index = 0
            sperrung = 1
            print("Richtig")
            abdeckFarbe = Color.white
        } else if index == 2 && rateBild1 != rateBild2 {
            index = 0
            sperrung = 0
            print("Falsch")
            abdeckFarbe = Color.blue
        }
        print(ID)
    }
    var body: some View {
      Button(action: {
            // Maybe obsolete later
            //self.knopfGedrueckt.toggle()
            abdeckFarbe = Color.white
// Call the comparison function          
Vergleich()
           if sperrung == 1 {
                self.knopfGesperrt.toggle()
              print("Gesperrt")
            }
            
        }, label: {
            Image(systemName: symbol)
                .padding(.all)
                .frame(width: 70.0, height: 70.0)
                .border(Color.black width: 1)
                .font(.system(size: 50, weight: .light))
                //.background(knopfGedrueckt ? Color.blue : Color.white)
                .background(abdeckFarbe)
        })
        // If "knopfGestperrt" changes to true, then deactivate the button.
        .disabled(knopfGesperrt)
    }
}

This is the whole code.

Thanks for showing the whole code. That helps me understand how your buttons are organized.

(Unfortunately, using many, many, super many global variables making the code hard to read, and difficult to maintain or modify. I hope the next step of your exercise would be something to remove all the global variables and re-define them in some appropriate places. But that is another issue.)


As far as I see your code,
  • you have 8 buttons (embedded inside the subview Taste)

  • their symbols are modified, independently

  • their background are modified together to the same value

Why don't you simply make knopf1...knopf8 an Array?
Code Block
struct ContentView: View {
// Placeholder variables before the real symbols are written to the buttons
@State private var knopf = Array(repeating: "questionmark", count: 8)
@State private var abdeckFarbe = Color.blue
var body: some View {
VStack {
Spacer()
// First row
HStack {
// The struct "Taste" below is called several times to draw the buttons.
ForEach(0..<4) {i in
Taste(symbol: knopf[i])
.background(abdeckFarbe)
}
}
// Second row
HStack {
ForEach(4..<8) {i in
Taste(symbol: knopf[i])
.background(abdeckFarbe)
}
}
Spacer()
// The cards are mixed.
Button(action: {
// Initialising the routine to re-mix the card with every tap on this button.
knopf = Array(repeating: "questionmark", count: 8)
bilder = ["moon", "moon", "house", "house", "sunset", "sunset", "cloud", "cloud"]
abdeckFarbe = Color.orange
knopf = bilder.shuffled()
//↓Are these really needed to be kept in global variables?
bilder = []
anzahl = 0
}, label: {
Text("Mischen")
})
}
}
}



Why don't you simply make knopf1...knopf8 an Array?

Because I am a beginner :-) But your code only writes the placeholder questionsmark on the buttons, not the symbols from the array "bilder".

Anyway, this is not the very problem. I still need a way to tell the program to call a specific button and change its color and symbol. I think this works only with several @State private var, because they work in the whole swift.file and every occurrence of this special variable reacts suddenly on changes. This will the code make even bulkier.

But your code only writes the placeholder questionsmark on the buttons, not the symbols from the array "bilder".

I guess you think so because you are a beginner.

When you could clarify your requirements, I would re-visit this thread. Good luck.

How shall I explain it other than I already did several times? Okay, away from those buttons. Take this simple example with texts below. What do I have to do to let the big orange button do what its label says?

Code Block
import SwiftUI
struct Test: View {
  var body: some View {
        VStack {
            Text("This is text 1")
                .foregroundColor(.green)
                .border(Color.black, width: 1)
           Text("This is text 2")
                .foregroundColor(.blue)
                .border(Color.black, width: 1)
  
            Button(action: {
   // The code?
            }, label: {
                Text("Set foregroundColor only of text 1 to purple,  make its border width 3 and set the border color only of text 2 to gray")
                    .font(.system(size: 30))
                    .foregroundColor(Color.black)
                    .background(Color.orange)
            })
            .padding(.top)
        }
    }
}
struct Test_Previews: PreviewProvider {
    static var previews: some View {
        Test()
    }
}

And now imagine that I have many of those texts (buttons) which I have to alter. It would be very helpful if I could tell Xcode "Change the color of Text 1" or: "Create a loop to change the attributes of Text 1...X".

I hope that you can get my point now.

How shall I explain it other than I already did several times?

Showing a code would better explain.

What do I have to do to let the big orange button do what its label says?

All the same. Simply make an Array. You just need more attribute than a single String.
Code Block
import SwiftUI
struct TextAttribute {
var text: String
var foregroundColor: Color
var borderColor: Color
var borderWidth: CGFloat
}
struct Test: View {
@State var attributes: [TextAttribute] = [
TextAttribute(text: "This is text 1", foregroundColor: .green,
borderColor: .black, borderWidth: 1),
TextAttribute(text: "This is text 2", foregroundColor: .blue,
borderColor: .black, borderWidth: 1),
]
var body: some View {
VStack {
ForEach(0..<2) {i in
Text(attributes[i].text)
.foregroundColor(attributes[i].foregroundColor)
.border(attributes[i].borderColor, width: attributes[i].borderWidth)
}
Button(action: {
//Set foregroundColor only of text 1 to purple
attributes[0].foregroundColor = .purple
//make its border width 3
attributes[0].borderWidth = 3
//the border color only of text 2 to gray
attributes[1].borderColor = .gray
}, label: {
Text("Set foregroundColor only of text 1 to purple, make its border width 3 and set the border color only of text 2 to gray")
.font(.system(size: 30))
.foregroundColor(Color.black)
.background(Color.orange)
})
.padding(.top)
}
}
}



How to call a SwiftUI button by its UUID?
 
 
Q