This question will probably come off as very basic, and something that probably can be found through searching, but despite my efforts of searching StackOverflow and just google I can't find any up-to-date thread or post regarding how to handle the different responses of a REST API, and, as I've found out, having an up-to-date thread is important to save trouble down the road when errors occur. So, to jump into it, I have an API endpoint on my server for logging in. It responds, as one would assume, with either two cases given login credentials;
If the login information succeeds, it returns this JSON Object:
{
"user": {
"id": 1,
"type": "user",
"name": "username",
"api_token": "accesstokenhere"
},
"access_token": "accesstokenhere"
}
If it doesn't succeed, it gives this response
{
"message": "Invalid credentials"
}
Now I have the login screen for my app, upon pressing "log in", submit the information to the server and get this response back, which is not of issue and very well documented. I have the following code so far:
import SwiftUI
import Combine
import Foundation
public struct UserModel: Decodable {
let id: Int
let username: String
let age: Int
enum CodingKeys: String, CodingKey {
case id = "id"
case username = "name"
case age = "age"
}
}
public struct UserResponse: Decodable {
public let user: UserModel
public let accessToken: String
enum CodingKeys: String, CodingKey {
case user = "user"
case accessToken = "access_token"
}
}
public class UserFetcher: ObservableObject {
public let objectWillChange = PassthroughSubject<UserFetcher,Never>()
@Published var hasFinished: Bool = false {
didSet {
objectWillChange.send(self)
}
}
var user: UserResponse?
@Published var incorrectLogin: Bool = false {
didSet {
objectWillChange.send(self)
}
}
init(){
guard let url = URL(string: "https://mywebsite.com/api/login") else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
do {
if let d = data {
let decodedRes = try JSONDecoder().decode(UserResponse.self, from: d)
DispatchQueue.main.async {
self.user = decodedRes
self.hasFinished = true
print("Dispatching")
}
} else {
print("No Data")
}
} catch {
print("Error")
}
}.resume()
}
}
I have taken this section in its entirety except for minor tweaks to fit the different object from another file I have for a similar task, albeit that it has no alternate responses and so I didn't have to handle any other types of data responses.
I'm still fairly new to swift, so I have basic understanding of do-try-catch syntax, but I don't how I would catch different response models or where to place them in my code to prevent any errors from happening.
Ideally, I would like it to toggle the incorrectLogin variable, which can be observed and trigger a popup saying incorrect login information, as all login screens do when you input incorrect credentials. If it doesn't, it should just toggle the hasFinished variable and leave incorrectLogin as false, and then I would use the user model to do all of the behind the scenes stuff.
Again, I'm still fairly new to swift, I'm sure there's probably security issues here or something else I'm overlooking, and please, let me know if that's the case.