I show username in list with API. When any name is clicked, I want to get that user's information, but I can't see any text on the screen. I don't understand where I went wrong. I would be glad if you help.
JSON
struct HastaInsertModel: Codable {
let ad, adres: String
let changeby: Int
let changedate, createdate, dogumyili, email: String
let hastaid: Int
let ilce: String
let klinikid, kullaniciid: Int
let phone, sehir, soyad: String
let tcno: String?
let ulke: String
let yakinlik: String?
}
CODE
class Webservice
func getAllHastaInfo(token: String, email: String, completion: @escaping (Result<[HastaInsertModel], NetworkError>) -> Void){
guard let url = URL(string: "http://ec2-3-74-42-117.eu-central-1.compute.amazonaws.com:8080/dentistodayapis/gethasta") else {
completion(.failure(.invalidURL))
return
}
var request = URLRequest(url: url)
request.addValue("\(token)", forHTTPHeaderField: "credentialtoken")
request.addValue("\(email)", forHTTPHeaderField: "username")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
completion(.failure(.noData))
return
}
do{
let informations = try JSONDecoder().decode([HastaInsertModel].self, from: data)
completion(.success(informations))
} catch {
print(String(data: data, encoding: .utf8))
print(error)
completion(.failure(.decodingError))
}
}.resume()
}
class PatientViewModel: ObservableObject {
@Published var items = [HastaInsertModel]()
@Published var hastalar: [HastaViewModel] = []
func getHastaInfo() {
let defaults = UserDefaults.standard
guard let token = defaults.string(forKey: "jsonwebtoken") else {
return
}
guard let email = defaults.string(forKey: "email") else {
print("Haa")
return
}
Webservice().getAllHastaInfo(token: token, email: email) { result in
switch result {
case .success(let hastalar):
DispatchQueue.main.async {
self.hastalar = hastalar.map(HastaViewModel.init)
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
struct HastaViewModel{
let hasta: HastaInsertModel
let id = UUID()
var ad: String {
return hasta.ad
}
var adres: String {
return hasta.adres
}
var dogumyili: String {
return hasta.dogumyili
}
var email: String {
return hasta.email
}
var ilce: String {
return hasta.ilce
}
var phone: String {
return hasta.phone
}
var sehir: String {
return hasta.sehir
}
var soyad: String {
return hasta.soyad
}
var tcno: String {
return hasta.tcno ?? "empty"
}
var ulke: String {
return hasta.ulke
}
var yakinlik: String {
return hasta.yakinlik ?? "empty"
}
}
@StateObject private var patientVM = PatientViewModel()
var body: some View {
List {
ForEach(patientVM.hastalar, id: \.id){ patient in
NavigationLink {
PatientDetail()
} label: {
VStack(alignment: .leading){
Text(patient.ad)
Text(patient.email).font(.caption).foregroundColor(.gray)
}
}
}
}
struct PatientDetail: View {
@StateObject private var patientVM = PatientViewModel()
var body: some View {
VStack {
Form {
Section(header: Text("Kişisel Bilgiler")) {
List (patientVM.hastalar, id:\.id){ patient in
Text("\(patient.ad)d")
Text("\(patient.soyad)")
Text("\(patient.phone)")
Text("\(patient.email)")
Text("\(patient.dogumyili)")
Text("\(patient.ulke)")
Text("\(patient.sehir)")
Text("\(patient.ilce)")
Text("\(patient.adres)")
Text("\(patient.tcno)")
}
}
For example, when I click "test new user", I show the patientdetail screen and I want to see the user's information.
I fixed it
struct PatientDetail: View {
private let patient: HastaViewModel
var body: some View {
VStack {
Form {
Section(header: Text("Kişisel Bilgiler")) {
Text("\(patient.ad)")
Text("\(patient.soyad)")
Text("\(patient.phone)")
Text("\(patient.email)")
Text("\(patient.dogumyili)")
Text("\(patient.ulke)")
Text("\(patient.sehir)")
Text("\(patient.ilce)")
Text("\(patient.adres)")
Text("\(patient.tcno)")
}
}
}
}
So that you only show one user/patient instead of a list of users. And then call it from the main view like
List {
ForEach(patientVM.hastalar, id: \.id){ patient in
NavigationLink {
PatientDetail(patient: patient)
} label: {
VStack(alignment: .leading) {
Text(patient.ad)
Text(patient.email).font(.caption).foregroundColor(.gray)
}
}