I want to print the information of the login user on the screen, but I fail
typeMismatch(Swift.Array, Swift.DecodingError.Context(codingPath:
[], debugDescription: "Expected to decode Array but found a
dictionary instead.", underlyingError: nil))
My current JSON model look like this:
{
"ad": "Mobile API",
"adres": "1",
"aversiyon": 0,
"changeby": 113,
"changedate": "2022-06-10Z",
"createdate": "2022-06-10Z",
"dogumyili": "1930",
"email": "mobileapi@asy.com",
"gversiyon": 0,
"ilce": "Beşiktaş",
"klinikid": 0,
"kullaniciid": 113,
"kversiyon": 0,
"phone": "(537) 226-6433",
"profil": "Hasta Profili",
"resifre": "TVsXh+6Uoiie4daIpI3ojw==",
"rversiyon": 0,
"sehir": "İstanbul",
"sifre": "TVsXh+6Uoddsie4daIpI3ojw==",
"soyad": "Test",
"tcno": "",
"ulke": "Türkiye"
}
Code:
struct MemberModel: Codable {
let ad, adres: String
let aversiyon, changeby: Int
let changedate, createdate: String
let dogumyili, email: String
let gversiyon: Int
let ilce: String
let klinikid, kullaniciid, kversiyon: Int
let phone, profil, resifre: String
let rversiyon: Int
let sehir, sifre, soyad: String
let tcno: String?
let ulke: String
}
func getAllMemberInformation(token: String, email: String, completion: @escaping (Result<[MemberModel], NetworkError>) -> Void){
guard let url = URL(string: "http://ec2-3-74-42-117.eu-central-1.compute.amazonaws.com:8080/dentistodayapis/getkullanici") 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([MemberModel].self, from: data)
completion(.success(informations))
} catch {
print(String(data: data, encoding: .utf8) as Any)
print(error)
completion(.failure(.decodingError))
print("\(email)")
print("\(token)")
}
}.resume()
}
class MemberViewModel: ObservableObject {
@Published var members:[MemberVM] = []
func getAllInformations(){
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().getAllMemberInformation(token: token, email: email) { result in
switch result {
case .success(let members):
DispatchQueue.main.async {
self.members = members.map(MemberVM.init)
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
}
struct MemberVM {
let member: MemberModel
let id = UUID()
var ad: String {
return member.ad
}
var soyad: String {
return member.soyad
}
var email: String {
return member.email
}
var phone: String {
return member.phone
}
var dogumyili: String {
return member.dogumyili
}
var ulke: String {
return member.ulke
}
var sehir:String {
return member.sehir
}
var ilce: String {
return member.ilce
}
var adres: String {
return member.adres
}
var tcno: String {
return member.tcno ?? "empty"
}
}
View:
List(memberVM.members, id:\.id) { member in
VStack{
Text("\(member.ad)")
Spacer()
Text("\(member.soyad)")
}
}
Xcode keeps giving me the error "Expected to decode Array but found a dictionary instead". I don't understand what it mean here. More precisely, I did not understand what to do. I used the same code to pull other information from JSON and it worked there. I looked at the answers to the questions asked under this title before, but I could not get an answer to my question. How can I fix this?
Post
Replies
Boosts
Views
Activity
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 have screen to register user. I have a post api for this. But I am not able to register the user. I don't understand where I went wrong. I would be glad if you help.
MODEL:
struct NewUserModel: Codable {
let name: String?
let address: String?
let year: String?
let email: String?
let district: String?
let phone: String?
let repassword: String?
let city: String?
let password: String?
let surname: String?
let tcno: String?
let city: String?
}
WebService Class
class Webservice {
func regisUser(email: String, password: String, repassword: String, name: String, surname: String, phone: String, year: String, city: String, country: String, district: String, address: String, tcno: String, completion: @escaping (Result<String, AuthenticationError>) -> Void) {
guard let url = URL(string: "http://ec2-3-74-42-117.eu-central-1.compute.amazonaws.com:8080/api/insertuser") else {
completion(.failure(.custom(errorMessage: "URL is not correct")))
return
}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
let request = NewUserModel(name: name, address: address, year: year, email: email, district: district, phone: phone, repassword: repassword, city: city, password: password, surname: surname, tcno: tcno, ulke: ulke)
do {
let requestBody = try JSONEncoder().encode(request)
urlRequest.httpBody = requestBody
urlRequest.addValue("application/json", forHTTPHeaderField: "content-type")
}catch let error {
debugPrint(error.localizedDescription)
}
URLSession.shared.dataTask(with: urlRequest) { (data, httpUrlResponse, error) in
if(data != nil && data?.count != 0)
{
do {
let response = try JSONDecoder().decode([NewUserModel].self, from: data!)
print("Success")
}
catch let decodingError {
debugPrint(decodingError)
}
}
}.resume()
}
}
When I press the register button, it does not register the user, but it prints success to the console.
LoginPageViewModel
@Published var email: String = ""
@Published var password: String = ""
@Published var repassword: String = ""
@Published var name: String = ""
@Published var surname: String = ""
@Published var phone: String = ""
@Published var year: String = ""
@Published var city: String = ""
@Published var city: String = ""
@Published var district: String = ""
@Published var address: String = ""
@Published var tcno: String = ""
func Register(){
Webservice().regisUser(email: email, sifre: sifre, resifre: resifre, ad: ad, soyad: soyad, phone: phone, dogumyili: dogumyili, ulke: ulke, sehir: sehir, ilce: ilce, adres: adres, tcno: tcno) { result in
switch result {
case .success(_):
DispatchQueue.main.async {
print("ok) }
case .failure(let error):
print(error.localizedDescription)
}
}
}
LoginPage View
@StateObject var loginData: LoginPageModel = LoginPageModel()
// Login Button...
Button {
if loginData.registerUser{
loginData.Register()
}
else{
loginData.Login()
}
There is a register screen I created to register the user to the app, but I cannot register the user. In xcode console it says "statusCode should be 2xx, but is 500"
Where am I doing wrong? Could you help?
PostModel JSON
struct PostModel: Codable {
let ad: String
let soyad: String
let email: String
let phone: String
let dogumyili: String
let ulke: String
let sehir: String
let ilce: String
let adres: String
let sifre: String
let resifre: String
}
NetworkManager
class NetworkManager {
static let shared = NetworkManager()
func postData(post: PostModel, completion: @escaping (Result<Data, Error>) -> (Void)) {
let parametrs: [String: Any] = [
"ad": post.ad,
"soyad": post.soyad,
"email": post.email,
"phone": post.phone,
"dogumyili": post.dogumyili,
"ulke": post.ulke,
"sehir": post.sehir,
"ilce": post.ilce,
"adres": post.adres,
"sifre": post.sifre,
"resifre": post.resifre
]
guard let url = URL(string: "www.sampleapi.com/sampleapi") else {
return
}
var request = URLRequest(url: url)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = parametrs.percentEncoded()
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else {
print("error", error ?? URLError(.badServerResponse))
return
}
guard (200 ... 299) ~= response.statusCode else {
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
do {
let response = try JSONSerialization.data(withJSONObject: data, options: .fragmentsAllowed)
completion(.success(response))
} catch {
completion(.failure(error))
}
}
task.resume()
}
}
extension Dictionary {
func percentEncoded() -> Data? {
map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
RegisterButton
Button {
NetworkManager.shared.postData(post: PostModel(ad: loginData.ad, soyad: loginData.soyad, email: loginData.email, phone: loginData.phone, dogumyili: loginData.dogumyili, ulke: loginData.ulke, sehir: loginData.sehir, ilce: loginData.ilce, adres: loginData.adres, sifre: loginData.sifre, resifre: loginData.resifre)) { result in
switch result {
case .success(let result):
print(result)
case .failure(let error):
print(error)
}
}
App registers the user to the server but still gives an error. When I press the register button, the user registers, but the application crashes.
After the application crashes, xcode displays the following screen.
It shows the error is here
Full code here
func Register(post: NewUserModel, completion: @escaping (Result<Data, Error>) -> (Void)) {
let parametrs: [String: Any] = [
"ad": post.ad,
"soyad": post.soyad,
"email": post.email,
"phone": post.phone,
"dogumyili": post.dogumyili,
"ulke": post.ulke,
"sehir": post.sehir,
"ilce": post.ilce,
"adres": post.adres,
"sifre": post.sifre,
"resifre": post.resifre
]
guard let url = URL(string: "http://ec2-3-74-42-117.eu-central-1.compute.amazonaws.com:8080/dentistodayapis/insertkullanici") else { return }
var request = URLRequest(url: url)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = try! JSONSerialization.data(withJSONObject: parametrs)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard
let data = data,
let response = response as? HTTPURLResponse,
error == nil
else {
print("error", error ?? URLError(.badServerResponse))
return
}
print(String(data: data, encoding: .utf8) as Any)
guard (200 ... 299) ~= response.statusCode else {
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
do {
let response = try JSONSerialization.data(withJSONObject: data, options: .fragmentsAllowed)
completion(.success(response))
} catch {
completion(.failure(error))
}
}
task.resume()
}
How can I get rid of the app crashing?
Hello, I can't show the questions on the screen.
I made Text(triviaManager.question) in View but it doesn't show the text on the screen
JSON
[
{
"description": 0,
"disid": 13,
"question": "Hypertension",
"lastmonth": 0
},
{
"description": 0,
"disid": 14,
"question": "Diabetes",
"lastmonth": 0
},
{
"description": 0,
"disid": 15,
"question": "Rheumatic Disease",
"lastmonth": 0
}
]
struct Trivia: Decodable {
var results: [Result]
struct Result: Decodable, Identifiable {
var id: UUID {
UUID()
}
var description: Int
var disid: Int
var question: String
var lastmonth: Int
var formattedQuestion: AttributedString {
do {
return try AttributedString(markdown: question)
} catch {
print("Error setting formattedQuestion: \(error)")
return ""
}
}
}
}
class TriviaManager
func fetchTrivia(token: String, email: String) async {
guard let url = URL(string: "http://ec2-3-74-42-117.eu-central-1.compute.amazonaws.com:8080/dentistodayapis/getanamnez/80") else { fatalError("Missing URL") }
var urlRequest = URLRequest(url: url)
urlRequest.addValue("\(token)", forHTTPHeaderField: "credentialtoken")
urlRequest.addValue("\(email)", forHTTPHeaderField: "username")
do {
let (data, response) = try await URLSession.shared.data(for: urlRequest)
guard (response as? HTTPURLResponse)?.statusCode == 200 else { fatalError("Error while fetching data") }
let decoder = JSONDecoder()
// Line below allows us to convert the correct_answer key from the API into the correctAnswer in our Trivia model, without running into an error from the JSONDecoder that it couldn't find a matching codingKey
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decodedData = try decoder.decode(Trivia.self, from: data)
DispatchQueue.main.async {
// Reset variables before assigning new values, for when the user plays the game another time
self.index = 0
self.trivia = decodedData.results
// self.length = self.trivia.count
self.setQuestion()
}
} catch {
print("Error fetching : \(error)")
}
}
I'm making a POST function but I'm getting an error. I am getting "HTTP Status 400 – Bad Request" error in console. In the simulator, it says "Something went wrong. Please try again later" on the screen. I don't understand where I am making the mistake. I need to fix this error urgently. Could you help?
JSON Model:
struct TaniTalep: Encodable {
let photo: Data?
let xray: Data?
let talep: String
init(photo: UIImage?, xray: UIImage?, talep: Talep) throws {
self.photo = photo?.pngData()
self.xray = xray?.pngData()
let jsonData = try JSONEncoder().encode(talep)
self.talep = String(data: jsonData, encoding: .utf8)!
}
}
struct Talep: Codable {
let tanitalepid: Int
let hastaid: Int
let cevap: String
let anamnezList: [Anamnez]
let sikayetanaList: [SikayetAna]
let sorucevapList: [SoruCevap]
struct SoruCevap: Codable {
let sikayetsoruid: Int
let soru: String
let sorucevap: String
}
struct SikayetAna: Codable {
let sikayet: String
let sikayetanaid: Int
}
struct Anamnez: Codable {
let aciklama: String
let anamnezid: Int
let cevap: String
let nitelik: String
let sonaltiay: String
}
}
Web Service:
func postTaniTalep(token: String, email: String, tanitalepid: Int, taniTalep: TaniTalep) async throws -> Bool {
guard let url = URL(string: "http://ec2-3-74-42-117.eu-central-1.compute.amazonaws.com:8080/dentistodayapis/inserttanitalep") else {
throw NetworkError.invalidURL
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
// request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("\(token)", forHTTPHeaderField: "credentialtoken")
request.addValue("\(email)", forHTTPHeaderField: "username")
request.addValue("IOS", forHTTPHeaderField: "platform")
request.addValue("TR", forHTTPHeaderField: "langcode")
let formData = try JSONEncoder().encode(taniTalep)
print("\(Date())-\(#line)--\(#function)--formData: \(String(data: formData, encoding: .utf8))-")
request.httpBody = formData
let (data, response) = try await URLSession.shared.data(for: request)
print(url)
print(String(data: data, encoding: .utf8))
return (response as? HTTPURLResponse)?.statusCode == 200
}
View:
final class TaniTalepViewModel: ObservableObject {
static let shared = TaniTalepViewModel()
init() {}
var hastaID: Int?
var cevap: String?
var soruCevapList = [Talep.SoruCevap]()
var sikayetAnaList = [Talep.SikayetAna]()
var anamnezList = [Talep.Anamnez]()
var photo: UIImage?
var xray: UIImage?
@Published var message: String?
@MainActor
func postTaniTalep() async {
guard
let hastaID = hastaID,
let cevap = cevap
else {
assertionFailure("Insufficient data")
return
}
let defaults = UserDefaults.standard
guard let token = defaults.string(forKey: "jsonwebtoken") else {
return
}
guard let email = defaults.string(forKey: "email") else {
return
}
do {
let tanitalepid = try await Webservice().getSequenceNextval(token: token, email: email)
let success = try await Webservice().postTaniTalep(token: token, email: email, tanitalepid: tanitalepid, taniTalep: TaniTalep(photo: photo, xray: xray, talep: .init(tanitalepid: tanitalepid, hastaid: hastaID, cevap: cevap, anamnezList: anamnezList, sikayetanaList: sikayetAnaList, sorucevapList: soruCevapList)))
if success {
message = "Your registration number \(tanitalepid) has been completed successfully.\n \(tanitalepid) numaralı kaydınız başarıyla tamamlanmıştır."
} else {
message = "Something went wrong. Please try again later."
}
} catch {
print("\(Date())-\(#line)--\(#function)--error: \(error)-")
message = "Error while posting tani talep: \(error)"
}
}
}
struct TaniTalepView: View {
@ObservedObject private var viewModel = TaniTalepViewModel.shared
var body: some View {
ZStack {
Color.flesh
.ignoresSafeArea()
if let message = viewModel.message {
Text(message)
.padding()
} else {
ProgressView()
}
}
.task {
await viewModel.postTaniTalep()
}
}
}