POST 请求后在 swift 模型中访问值的问题
Posted
技术标签:
【中文标题】POST 请求后在 swift 模型中访问值的问题【英文标题】:Issues with accessing values in swift model after POST request 【发布时间】: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 又从何而来?我以前见过……不久前 【参考方案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 版本会更好。在这种情况下出错 我自己的代码复制粘贴错误,我编辑了代码)以上是关于POST 请求后在 swift 模型中访问值的问题的主要内容,如果未能解决你的问题,请参考以下文章