Ios 如何在不破坏MVVM模式的情况下处理Alamofire的结果
因此,我最近开始将代码迁移到MVVM模式,我遇到了一些问题。 目前,我正在使用我的登录页来验证用户。 问题是我调用了我的函数,但是我的代码没有等待它的响应,而是移动到下一行。我认为这是因为Alamofire的异步功能。 这是我的密码:Ios 如何在不破坏MVVM模式的情况下处理Alamofire的结果,ios,swift,alamofire,Ios,Swift,Alamofire,因此,我最近开始将代码迁移到MVVM模式,我遇到了一些问题。 目前,我正在使用我的登录页来验证用户。 问题是我调用了我的函数,但是我的代码没有等待它的响应,而是移动到下一行。我认为这是因为Alamofire的异步功能。 这是我的密码: //我的登录视图控制器 类loginPageViewController:UIViewController、UIExtFieldDelegate{ 私有变量viewModel=userViewModel() @IBOutlet弱var usernameTextFi
//我的登录视图控制器
类loginPageViewController:UIViewController、UIExtFieldDelegate{
私有变量viewModel=userViewModel()
@IBOutlet弱var usernameTextField:UITextField!
@IBOutlet弱var密码文本字段:UITextField!
@iAction func signInButton(\发送方:圆形按钮){
if(usernameTextField.text!=“”&passwordTextField.text!=“”){
self.viewModel.validate(nameField:self.usernameTextField.text!,passField:self.passwordtexfield.text!)
if(self.viewModel.isDone){
打印(“成功”)
self.presentPage(标识符:“homePageNavCtrl”)
}
}
}
重写func viewDidLoad(){
super.viewDidLoad()
usernameTextField.delegate=self
passwordTextField.delegate=self
}
func textField应该返回(textField:UITextField)->Bool{
usernameTextField.resignFirstResponder()
passwordTextField.resignFirstResponder()辞职
返回true;
}
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
self.view.endEditing(true)
}
}
专用扩展loginPageViewController{
func displayErrorMessage(errorMessage:String){
让alert=UIAlertController(标题:“错误”,消息:errorMessage,首选样式:UIAlertController.Style.alert)
addAction(UIAlertAction(标题:“确定”,样式:UIAlertAction.style.default,处理程序:nil))
self.present(警报、动画:true、完成:nil)
}
func presentPage(标识符:字符串){
让故事板:UIStoryboard=UIStoryboard(名称:“Main”,bundle:nil)
让nextViewController=storyBoard.InstanceVIEWCONTROLLER(带标识符:标识符)
self.present(nextViewController,动画:true,完成:nil)
}
}
我想做的是,当点击登录按钮时,使用JSON请求验证用户,如果凭据正确,则转到下一页
这是我的userViewModel
类userViewModel{
私有变量mng=restInterface()
private var User=User()
var isDone=false
变量id:Int{
返回用户ID
}
var用户名:String{
返回User.LOGINNAME
}
var密码:String{
返回User.PASSHASH
}
}
扩展用户视图模型{
func updateId(id:Int){
User.ID=ID
}
func updateUsername(用户名:字符串){
User.LOGINNAME=用户名
}
func updatePassword(密码:字符串){
User.PASSHASH=密码
}
func验证(名称字段:字符串,密码字段:字符串){
让accountBaseURL=“myUrlLiesDownHere”
var nm=nameField
var ps=通域
nm.插入(“”,位于:nm.startIndex)
nm.插入(“”,位于:nm.endIndex)
ps.insert(“”,位于:ps.startIndex)
ps.insert(“”,位于:ps.endIndex)
让参数:[String:String]=[“sUser”:nm,“sPass”:ps,“sToken”:“''']
self.mng.performRequest(URLString:accountBaseURL,参数:params,方法:.get,successCallback:{(dict)in
self.User.ID=dict.value(forKey:“ID”)as!Int
self.User.LOGINNAME=dict.value(forKey:“LOGINNAME”)作为!字符串
self.User.PASSHASH=dict.value(forKey:“PASSHASH”)作为!字符串
self.loginDone()
}){(错误)在
打印(“错误”)
}
}
func loginDone(){
self.isDone=true
}
}
这是我的rest接口
类rest接口{
func performRequest(URLString:String,参数:parameters,方法:HTTPMethod,successCallback:@escaping(NSDictionary)->Void,errorCallBack:@escaping(String)->Void)->Void{
请求(URLString,方法:方法,参数:参数).responseJSON{response in
打印(答复)
如果让JSON=response.result.value为?[String:Any]{
打印(JSON)
successCallback(JSON作为NSDictionary)
}否则{
errorCallBack(“JSON不存在”)
}
}
}
}
当我在视图控制器中控制它时,userViewModel上的isDone布尔值必须为true。但事实并非如此。当我按下按钮一次,结果变为真,但什么也没发生。当我再次点击它时,它会将我重定向到我想要的下一页。
因此,使用async确实让我感到困惑,我在这里寻求帮助:)谢谢…在您
UserViewModel
中,创建一个completionHandler
回调,并在viewController
中实现它,以显示下一个viewController
class UserViewModel {
public var loginCompletion: (()-> Void)?
private var mng = restInterface()
private var User = user()
// rest of your code
}
请求完成后调用completionHandler
extension userViewModel{
func validate(nameField: String, passField: String){
let accountBaseURL = "myUrlLiesDownHere"
var nm = nameField
var ps = passField
nm.insert("'", at: nm.startIndex)
nm.insert("'", at: nm.endIndex)
ps.insert("'", at: ps.startIndex)
ps.insert("'", at: ps.endIndex)
let params : [String: String] = ["sUser" : nm, "sPass" : ps, "sToken": "''"]
self.mng.performRequest(URLString: accountBaseURL, parameters: params, method: .get, successCallback: { (dict) in
self.User.ID = dict.value(forKey: "ID") as! Int
self.User.LOGINNAME = dict.value(forKey: "LOGINNAME") as! String
self.User.PASSHASH = dict.value(forKey: "PASSHASH") as! String
self.loginDone()
self.loginCompletion?()
}) { (error) in
print("Error")
}
}
func loginDone(){
self.isDone = true
}
}
completionHandler
在viewController
中的用法
class loginPageViewController: UIViewController, UITextFieldDelegate {
private var viewModel = userViewModel()
@IBOutlet weak var usernameTextField: UITextField!
@IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
usernameTextField.delegate = self
passwordTextField.delegate = self
self.viewModel.loginCompletion = { [weak self] in
print("success")
self?.presentPage(identifier: "homePageNavCtrl")
}
}
@IBAction func signInButton(_ sender: roundButton) {
if(usernameTextField.text != "" && passwordTextField.text != "") {
self.viewModel.validate(nameField: self.usernameTextField.text!, passField: self.passwordTextField.text!)
}
}
// rest of your code
}
注意:在Swift中,class/struct/enum
名称应以大写字母开头。上述解决方案是在视图模型之间观察数据的非常基本的设置。您应该寻找更好的数据绑定解决方案,例如,等。----更改验证方法-
func validate(nameField: String, passField: String, completionHandler: @escaping (_: NSDictionary?, _: NSError?) -> Void){
let accountBaseURL = "myUrlLiesDownHere"
var nm = nameField
var ps = passField
nm.insert("'", at: nm.startIndex)
nm.insert("'", at: nm.endIndex)
ps.insert("'", at: ps.startIndex)
ps.insert("'", at: ps.endIndex)
let params : [String: String] = ["sUser" : nm, "sPass" : ps, "sToken": "''"]
self.mng.performRequest(URLString: accountBaseURL, parameters: params, method: .get, successCallback: { (dict) in
self.User.ID = dict.value(forKey: "ID") as! Int
self.User.LOGINNAME = dict.value(forKey: "LOGINNAME") as! String
self.User.PASSHASH = dict.value(forKey: "PASSHASH") as! String
completionHandler(dict, nil)
}) { (error) in
print("Error")
completionHandler(nil, error)
}
}
@IBAction func signInButton(_ sender: roundButton) {
if(usernameTextField.text != "" && passwordTextField.text != "") {
self.viewModel.validate(nameField: self.usernameTextField.text!, passField: self.passwordTextField.text!) { (resultDict, error) in
if error != nil {
print("Error")
} else {
print("success")
self.presentPage(identifier: "homePageNavCtrl")
}
}
}
------方法调用的更改-
func validate(nameField: String, passField: String, completionHandler: @escaping (_: NSDictionary?, _: NSError?) -> Void){
let accountBaseURL = "myUrlLiesDownHere"
var nm = nameField
var ps = passField
nm.insert("'", at: nm.startIndex)
nm.insert("'", at: nm.endIndex)
ps.insert("'", at: ps.startIndex)
ps.insert("'", at: ps.endIndex)
let params : [String: String] = ["sUser" : nm, "sPass" : ps, "sToken": "''"]
self.mng.performRequest(URLString: accountBaseURL, parameters: params, method: .get, successCallback: { (dict) in
self.User.ID = dict.value(forKey: "ID") as! Int
self.User.LOGINNAME = dict.value(forKey: "LOGINNAME") as! String
self.User.PASSHASH = dict.value(forKey: "PASSHASH") as! String
completionHandler(dict, nil)
}) { (error) in
print("Error")
completionHandler(nil, error)
}
}
@IBAction func signInButton(_ sender: roundButton) {
if(usernameTextField.text != "" && passwordTextField.text != "") {
self.viewModel.validate(nameField: self.usernameTextField.text!, passField: self.passwordTextField.text!) { (resultDict, error) in
if error != nil {
print("Error")
} else {
print("success")
self.presentPage(identifier: "homePageNavCtrl")
}
}
}
谢谢你的回答,我也会试试这个!感谢您提供的绑定信息,请立即查看。