1

I am new in Swift, I am trying to build a test app in which I have people in a list, all works for inserting new people, I managed also swipe for delete, but I'm not able to find the right procedure to tap on a contact and open a sheet or a navigation view with all the details. I am using a MVVM, that's the code:

Model:

import Foundation

struct ClienteModel : Identifiable, Codable {

let id : String
let cognome : String
let nome : String
let indirizzo : String
let città : String
let telefono : String

init(id: String = UUID().uuidString, cognome: String, nome: String, indirizzo: String, città: String, telefono: String) {
    
    self.id = UUID().uuidString
    self.cognome = cognome
    self.nome = nome
    self.indirizzo = indirizzo
    self.città = città
    self.telefono = telefono
}
func updateCompletion() -> ClienteModel {
    return ClienteModel(id: id, cognome: cognome, nome: nome, indirizzo: indirizzo, città: città, telefono: telefono)
}
}

ViewModel:

import Foundation

class ListViewModel: ObservableObject {

@Published var clienti: [ClienteModel] = [] {
    didSet {
        salvaClienti()
    }
}
typealias storage = [ClienteModel]

let clientiKey : String = "clienti_list"

init() { caricaClienti()}

func caricaClienti() {
    guard
        let data = UserDefaults.standard.data(forKey: clientiKey),
        let clientiSalvati = try? JSONDecoder().decode([ClienteModel].self, from: data)
    else { return }
    self.clienti = clientiSalvati
    }


func cancellaCliente(indexSet: IndexSet) {
    clienti.remove(atOffsets: indexSet)
    }

func muoviCliente(from: IndexSet, to: Int) {
    clienti.move(fromOffsets: from, toOffset: to)

}

func aggiungiCliente(cognome: String, nome: String, indirizzo:String, città: String, telefono: String) {
    let nuovoCliente = ClienteModel(cognome: cognome, nome: nome, indirizzo: indirizzo, città: città, telefono: telefono)
    
    clienti.insert(nuovoCliente, at: 0)
    
    salvaClienti()
}

func aggiornaClienti(item: ClienteModel) {
    if let index = clienti.firstIndex(where: { $0.id == item.id}) {
        clienti[index] = item.updateCompletion()
    }
}

func salvaClienti() {
    if let encodedData = try? JSONEncoder().encode(clienti) {
        UserDefaults.standard.set(encodedData, forKey: clientiKey)
    }
}
}

And the ListView in which I stopped at onTap command :-(

import SwiftUI

struct ListView: View {

@EnvironmentObject var listViewModel : ListViewModel
//@State private var showingDetailView = false
//@State var selectedCliente: ClienteModel
//@State private var mostraSheet: Bool = false

var body: some View {
    ZStack {
        //        if listViewModel.clienti.isEmpty {
        //        Text("LISTA VUOTA")
        //    } else {
        List {
            ForEach(listViewModel.clienti) { item in
                ClienteRowView(cliente: item)}
            .onDelete(perform: listViewModel.cancellaCliente)
            .listStyle(InsetGroupedListStyle())
            .listRowInsets((EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 10)))
            .onTapGesture {
                
            }
            
            
        }
        
    }
    
    .toolbar {
        ToolbarItem(placement: .principal, content: {
            Text("ColorLite App")})}
    .navigationViewStyle(StackNavigationViewStyle())
    .navigationBarTitleDisplayMode(.inline)
    .navigationBarItems(
        //leading:
        //NavigationLink("Add", destination: AddView()),
        trailing:
            NavigationLink("Add", destination: AddView()))
  }
}

struct ListView_Previews: PreviewProvider {
static var previews: some View {
  //  let previewCliente = ClienteModel(cognome: "", nome: "", indirizzo: "", città: "", telefono: ""  )
    NavigationView {
        ListView()
}
    .environmentObject(ListViewModel())
}
}

Any help in simple words will be really appreciated... Thanks!

  • 1
    In SwiftUI we don't use view model objects we use @ State in the View struct so I would recommend learning that first. – malhal Jan 27 '22 at 00:13

1 Answers1

1

again the two of us :)
You should wrap the List in a NavigationView and then use NavigationLink which will get you to the DetailView. No need for TapGestures.

    NavigationView {
        List {
            ForEach(clienti) { item in
                NavigationLink {
                    ClienteDetailView(cliente: item)
                } label: {
                    ClienteRowView(cliente: item)
                }
            }
        }
        .listStyle(InsetGroupedListStyle())
    }
ChrisR
  • 9,523
  • 1
  • 8
  • 26
  • 1
    Hi again, thanks for you help, I've got a red in line ClienteDetailView(cliente: item) of course I changed ClienteDetailview with my DetailView name. My issue is also how to look and then edit name, surname, address etc fields in the Detailed View. :-( – Alessandro Bardelle Jan 27 '22 at 01:02
  • 1
    In the DetailView you can use a `Form` with `TextField`s for the single entries to edit. But I would recommend some tutorial that leads you through an App build-up. I can recommend hackingwithswift.com – it has a nice 100 days with SwiftUI course for free. – ChrisR Jan 27 '22 at 01:26