swift - 如何在 SwiftUI case.success 上保存两个值
问题描述
我正在 SwiftUI 中执行 API 调用以登录我的用户并获取令牌。
如果成功,我需要保存令牌和客户端值以供其他未来调用。
我不确定如何在 case.success 函数中将两个单独的值保存到用户默认值。当我也尝试保存客户端信息时,我遇到了元组错误。如果我只是想捕获令牌,则此登录功能可以正常工作。
我不想将这些值保存到模型中,因为我认为这不是安全的最佳做法。
成功执行此登录功能后,如何将令牌和客户端都设置为用户默认值?
这是我的网络电话:
import Foundation
import SwiftUI
enum AuthenticationError: Error {
case invalidCredentials
case custom(errorMessage: String)
}
struct LoginRequestBody: Codable {
let email: String
let password: String
}
struct LoginResponse: Decodable {
let data: LoginValue?
let success: Bool?
let client: String?
}
struct LoginValue: Decodable {
let message: String?
let user: UserRole?
let success: Bool?
}
struct UserRole: Decodable {
let role: String?
}
class Sessionservice {
func login(email: String, password: String, completion: @escaping (Result<String, AuthenticationError>) -> Void){
guard let url = URL(string: "https://example.com/api/v1/auth/sign_in") else {
completion(.failure(.custom(errorMessage:"Site is unavailable. Try again later.")))
return
}
let body = LoginRequestBody(email: email, password: password)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONEncoder().encode(body)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let response = response as? HTTPURLResponse {
guard let token = response.value(forHTTPHeaderField: "Accesstoken") else {
completion(.failure(.custom(errorMessage: "Missing Access Token")))
return
}
guard let client = response.value(forHTTPHeaderField: "client") else {
completion(.failure(.custom(errorMessage: "Missing Client")))
return
}
completion(.success(token))
completion(.success(client))
}
guard let data = data, error == nil else { return }
guard let loginResponse = try? JSONDecoder().decode(LoginResponse.self, from: data) else { return }
guard let messageData = loginResponse.data else {return}
guard let message = messageData.message else {return}
guard let userRole = messageData.user else {return}
guard let role = userRole.role else {return}
completion(.success(message))
completion(.success(role))
}.resume()
}
}
这是我的模型:
import Foundation
class LoginViewModel: ObservableObject {
var email: String = ""
var password: String = ""
@Published var isAuthenticated: Bool = false
@Published var authenticationDidFail: Bool = false
@Published var loginButtonClicked: Bool = false
func login() {
let defaults = UserDefaults.standard
self.loginButtonClicked = true
Sessionservice().login(email: email, password: password) { result in
switch result {
case.success(let token, let client):
defaults.setValue(token, forKey: "Accesstoken")
defaults.setValue(self.email, forKey: "userEmail")
defaults.setValue(client, forKey: "client")
DispatchQueue.main.async {
self.isAuthenticated = true
self.authenticationDidFail = false
self.loginButtonClicked = false
}
case.failure(let error):
DispatchQueue.main.async {
self.authenticationDidFail = true
self.isAuthenticated = false
self.loginButtonClicked = false
}
}
}
}
func fetchProjects() {
print("Fetching Projects")
}
}