【问题标题】:Issues with accessing values in swift model after POST requestPOST 请求后在 swift 模型中访问值的问题
【发布时间】:2019-07-19 10:55:12
【问题描述】:

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

模型类

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

【问题讨论】:

  • Result 又从何而来?我以前见过……不久前

标签: json swift post swiftui


【解决方案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
}

【讨论】:

  • 感谢@Scriptable 抱歉,如果我问了一个愚蠢的问题,但是,如果我将 loginUser 方法更改为您建议的方法,它仍然期待 Bool 返回值,那么我应该返回什么?其次,您提供的第二段代码,究竟是什么意思?在 loginUser 方法里面??
  • 是的,对不起,我忘了删除 -> Bool 部分,现在就这样做。最后一段代码是如何调用 loginUser 方法并使用值
【解决方案2】:

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 menthind,这是一个异步方法,因此您需要使用完成块而不是return

【讨论】:

  • UIImage 是从哪里来的?而且你不应该使用 NS 类,几乎总有一个 Swift 版本会更好。在这种情况下出错
  • 我自己的代码复制粘贴错误,我编辑了代码)
猜你喜欢
  • 2017-07-13
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多