Ios 如何在不破坏MVVM模式的情况下处理Alamofire的结果

Ios 如何在不破坏MVVM模式的情况下处理Alamofire的结果,ios,swift,alamofire,Ios,Swift,Alamofire,因此,我最近开始将代码迁移到MVVM模式,我遇到了一些问题。 目前,我正在使用我的登录页来验证用户。 问题是我调用了我的函数,但是我的代码没有等待它的响应,而是移动到下一行。我认为这是因为Alamofire的异步功能。 这是我的密码: //我的登录视图控制器 类loginPageViewController:UIViewController、UIExtFieldDelegate{ 私有变量viewModel=userViewModel() @IBOutlet弱var usernameTextFi

因此,我最近开始将代码迁移到MVVM模式,我遇到了一些问题。 目前,我正在使用我的登录页来验证用户。 问题是我调用了我的函数,但是我的代码没有等待它的响应,而是移动到下一行。我认为这是因为Alamofire的异步功能。 这是我的密码:

//我的登录视图控制器
类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")
            }
         }
     }

谢谢你的回答,我也会试试这个!感谢您提供的绑定信息,请立即查看。