json - POST 请求后在 swift 模型中访问值的问题

标签 json swift post swiftui

我是 swift 的初学者。遵循在线教程后,我成功地向我的 API 服务发出了 POST 请求,但是,我现在希望将 LoginResponse 模型类的值返回到 SwiftUI View 结构,以便我可以更改状态变量的值。

模型类

// 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))

        }

    }

}

登录 Controller

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 值??

最佳答案

当您调用您的 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
}

关于json - POST 请求后在 swift 模型中访问值的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57111006/

相关文章:

php - PayPal REST API 更新计费协议(protocol)

ios - 获取要在文本字段中显示的方法 JSON 数据不起作用(错误)

Swift:无法链接 DispatchGroup

javascript - jQuery、Ajax、WP、发布 4000B 长文本 : 404 not found (2000B=OK)?

json - EC2 实例类型的 AWS Cloudformation 模板错误

javascript - 关于d3.layout.pack()的几个简单问题

javascript - 在作为 EJS 模板传递以查看的字符串化 JSON 中转义单引号

ios - 快速:调用 willDisplay

ruby-on-rails - rails 4 : Force method: :post

security - 在 POST 请求上使用 XSS 窃取信息的场景是什么