Home > Software engineering >  Looping two arrays of different type items (string and image) with ForEach SwiftUI
Looping two arrays of different type items (string and image) with ForEach SwiftUI

Time:10-11

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)
                    }
                }
            }
        }
    }
}
  • Related