arraysswiftuiswiftui-list

Use a Modal to Add an Item from a List in SwiftUI


I would like to know how to add an item from a List included in a Modal so when I tap in a row, I can have the item selected in the First View that launched the sheet (to make clearer, the effect the you find when the iPhone app "Messages" select a contact from "Contacts").

Here's my basic code

struct Product : Hashable { 

  var name : String

  init(name: String) {
    self.name = name
  }

  func hash(into hasher: inout Hasher) {
    hasher.combine(name)
  }
}


class Manager {

  var product : [Product] = []

  init() {


    let pencil = Product(name: "Pencil")
    let eraser = Product(name: "Eraser")
    let ruler = Product(name: "Notebook")

    product = [pencil, eraser, ruler]

  }
}

struct FirstView: View {

  @State var isSheetOpened = false
  var products : Manager

  var body: some View {
      VStack {
      Button(action: {
          self.isSheetOpened.toggle()
      }) {
          Text("Add item from sheet")
      }
      .sheet(isPresented: self.$isSheetOpened) {
          Sheet(products: self.products, isSheetOpened: self.isSheetOpened)
      }

      Text("Add here")

    }
  }
}

struct Sheet: View {

  var products : Manager
  var isSheetOpened : Bool

  var body: some View {
      VStack {
          List {                
              ForEach(self.products.product, id: \.self) { index in
                Text(index.name)
            }
        }
    }
  }
}

Solution

  • check this out:

    import SwiftUI
    
    struct Product : Hashable {
        
        var name : String
        
        init(name: String) {
            self.name = name
        }
        
        func hash(into hasher: inout Hasher) {
            hasher.combine(name)
        }
    }
    
    
    class Manager : ObservableObject {
        
        @Published var chosenProducts : [Product] = []
        var products : [Product] = []
        
        init() {
            
            let pencil = Product(name: "Pencil")
            let eraser = Product(name: "Eraser")
            let ruler = Product(name: "Notebook")
            
            products = [pencil, eraser, ruler]
        }
    }
    struct ContentView: View {
        
        @EnvironmentObject var manager : Manager
        
        @State var isSheetOpened = false
        
        var body: some View {
            VStack {
                Button(action: {
                    self.isSheetOpened.toggle()
                }) {
                    Text("Add item from sheet")
                }
                Text("Chosen products")
                    .font(.largeTitle)
                List {
                    ForEach(self.manager.chosenProducts, id: \.self) { product in
                        Text(product.name)
                    }
                }
                .sheet(isPresented: self.$isSheetOpened) {
                    Sheet(isSheetOpened: self.$isSheetOpened)
                        .environmentObject(self.manager)
                }
                
                Text("Add here")
                
            }
        }
    }
    
    struct Sheet: View {
        
        @EnvironmentObject var manager : Manager
        
        @Binding var isSheetOpened : Bool
        
        var body: some View {
            VStack {
                List (self.manager.products, id: \.self) { product in
                    Button(action: {
                        self.manager.chosenProducts.append(product)
                        self.isSheetOpened = false
                    }) {
                        Text(product.name)
                    }
                }
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView().environmentObject(Manager())
        }
    }