我是个完全敏捷的初学者。在完成在线教程之后,我成功地向API服务发出了POST请求,但是,现在我希望将LoginResponse
模型类的值返回到SwiftUI视图结构,以便可以更改a的值状态变量。
模型类
// MARK: - LoginResponse
class LoginResponse: Codable {
let message, oauthToken, status: String
let userData: [UserDatum]
enum CodingKeys: String, CodingKey {
case message
case oauthToken = "oauth_token"
case status
case userData = "user_data"
}
init(message: String, oauthToken: String, status: String, userData: [UserDatum]) {
self.message = message
self.oauthToken = oauthToken
self.status = status
self.userData = userData
}
}
// MARK: - UserDatum
class UserDatum: Codable {
let emailAddress, firstName, lastName, phoneNumber: String
let userID: String
let userOnboardStage: Int
enum CodingKeys: String, CodingKey {
case emailAddress = "email_address"
case firstName = "first_name"
case lastName = "last_name"
case phoneNumber = "phone_number"
case userID = "user_id"
case userOnboardStage = "user_onboard_stage"
}
init(emailAddress: String, firstName: String, lastName: String, phoneNumber: String, userID: String, userOnboardStage: Int) {
self.emailAddress = emailAddress
self.firstName = firstName
self.lastName = lastName
self.phoneNumber = phoneNumber
self.userID = userID
self.userOnboardStage = userOnboardStage
}
}
网络服务类
enum APIError:Error{
case responseProblem
case decodingProblem
case encodingProblem
}
struct APIRequest {
let resourceURL: URL
let parameters: Dictionary<String, String>
init(endpoint: String, email: String, password: String){
let resourceString = "https://someurl/\(endpoint)"
guard let resourceURL = URL(string: resourceString) else {fatalError()}
self.resourceURL = resourceURL
var parameters = Dictionary<String, String>()
parameters = ["email_address":email,
"password":password,
"user_device_token":"",
"client_id":"",
"client_secret":""]
self.parameters = parameters
}
func save(_ loginResponseToSave:LoginResponse, completion: @escaping(Result<LoginResponse, APIError>) -> Void){
do {
var urlRequest = URLRequest(url : resourceURL)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpBody = try JSONEncoder().encode(self.parameters)
let dataTask = URLSession.shared.dataTask(with: urlRequest){ data , response, _ in
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, let jsonData = data else {
completion(.failure(.responseProblem))
return
}
do {
let loginData = try JSONDecoder().decode(LoginResponse.self, from: jsonData)
completion(.success(loginData))
}catch{
completion(.failure(.decodingProblem))
}
}
dataTask.resume()
}catch{
completion(.failure(.encodingProblem))
}
}
}
登录控制器
class Login {
// This function is called from the view
func loginUser(email:String, password:String) -> Bool{
let loginRequest = LoginResponse(message: "", oauthToken: "", status: "", userData: [])
let postRequest = APIRequest(endpoint: "login_buyer", email: email, password: password)
postRequest.save(loginRequest, completion:{ result in
switch result{
case .success(let status):
print(status.status) < ---- I want to access this value outside of this scope
case .failure(let error):
print(error)
}
})
/// I want to return it here
return status.status <---- for example
}
}
我希望能够访问LoginResponse模型中保存的值,但是当尝试访问它时,我得到了nil
值?
答案 0 :(得分:1)
您在调用API时正在执行异步请求,该请求将在后台运行,并且该函数将在完成之前返回,因此您需要像其他地方一样使用完成处理程序...或对数据返回并在范围内时。
您很可能会像这样更新您的方法:
func loginUser(email:String, password:String, completion: (LoginResponse?) -> Void)
然后
switch result {
case .success(let loginResponse):
print(loginResponse)
completion(loginResponse)
case .failure(let error):
print(error)
completion(nil)
}
以及当您致电loginUser时:
loginUser(email: "email", password: "pwd") { response in
guard let loginResponse = response else { return }
// do something here with the response
}
答案 1 :(得分:0)
Ben,您可以像这样重写 loginUser()方法:
class Login {
typealias CompletionHandler = (Result<Strin, Error>) -> Void
func loginUser(email:String, password:String, completion: @escaping CompletionHandler) -> Bool{
let loginRequest = LoginResponse(message: "", oauthToken: "", status: "", userData: [])
let postRequest = APIRequest(endpoint: "login_buyer", email: email, password: password)
postRequest.save(loginRequest, completion:{ result in
switch result{
case .success(let status):
completion(.success(status.status))
print(status.status)
case .failure(let error):
completion(.failure(error))
}
})
}
}
作为@Scriptable menthiond,这是一个异步方法,因此,您需要使用完成块,而不是 return 。