In stead to have an array of image under an array of text, I would like to have one array alternatively with image or text depending if I push the button text or the button picture.
Here is what I have tried:
struct HistoryPicture: Identifiable {let id = UUID ()
var picture: Image?}
struct HistoryText: Identifiable {let id = UUID ()
var text: String?}
struct ContentView: View {
@State var archivePicture: [HistoryPicture] = []
@State var archiveText: [HistoryText] = []
var body: some View {ScrollView{
VStack(spacing:20){
ForEach(self.archiveText) { item in
Text("<text>")
}
ForEach(self.archivePicture) { item in
Image("simpson")
}
// Button Text
HStack{
Button {var newHistory = HistoryText()
newHistory.text = "<text>"
self.archiveText.append(newHistory)
} label: { Circle()
.fill(Color.black)
.frame(width: 70, height: 70)} }
// Button Picture
HStack{
Button {var newHistoryPicture = HistoryPicture()
newHistoryPicture.picture = Image("simpson")
self.archivePicture.append(newHistoryPicture)
} label: { Circle()
.fill(Color.red)
.frame(width: 70, height: 70)
}} }} }}
CodePudding user response:
With this solution you get the results in the order the buttons were pressed. For that you just need one ForEach with one struct. If you want more complex views inside the ForEach, I would suggest using Protocols or inheritance.
struct HistoryItem: Identifiable {
let id = UUID()
var text: String?
var imageName: String?
}
struct ContentView: View {
@State var items = [HistoryItem]()
var body: some View {
ScrollView {
VStack(spacing: 20){
ForEach(items) { item in
if let text = item.text {
Text(text)
} else if let imageName = item.imageName {
Image(imageName)
}
}
HStack {
Button {
let newItem = HistoryItem(text: "<text>")
items.append(newItem)
} label: {
Circle()
.fill(Color.black)
.frame(width: 70, height: 70)
}
Button {
let newItem = HistoryItem(imageName: "simpson")
items.append(newItem)
} label: {
Circle()
.fill(Color.red)
.frame(width: 70, height: 70)
}
}
}
}
}
}