首页 > 解决方案 > 从视图控制器的分离文件中呈现视图控制器

问题描述

我有这个应用程序,它使用 Alamofire 向后端发送请求,该后端会返回响应,并根据响应应用程序执行操作。我发现 Alamofire 代码对我的项目来说太混乱了,我想将代码解析为一行代码。为此,我将 Alamofire 代码块放在我的一个自定义框架库中的一个名为 Requests 的类中。每次我从后端得到响应时,我都想运行一个函数(不是问题),然后执行 segue/present/push 到下一个视图控制器(问题)。

假设我有一个 Request 类,其中包含一个 login() 函数,该函数接受用户名和密码参数。调用此函数时的一行代码如下所示:Request.login(username, password)and Request.logout()finally 等。此函数可以在同一个 Xcode 项目中的 ACommonLibrary 框架中找到。这将运行 Alamofire 代码以发送请求,然后以 JSON 格式获得“authenticated: true”的响应,并据此应用程序将 segue/present/push 到 Profile 视图控制器。

我尝试使用布尔值执行此操作,如果我收到响应,则变量将从 false 设置为 true 并由函数返回,因此我可以在 if/else 语句中使用它,但这不起作用。我正常尝试了

let storyboard:UIStoryboard = UIStoryboard(name: "login", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Login") as! LoginViewController
self.present(vc, animated: true, completion: nil)

但我得到实例成员'present' cannot be used on type 'Request' 然后我发现有人问如何从分离的视图控制器中呈现视图控制器?但这也不起作用,假设是因为我在一个情节提要中有多个视图控制器。

我搜索了这个错误和其他类似的错误无济于事。所以现在我质疑这甚至可能实现还是我必须以不同的方式处理它?任何建议都值得赞赏。提前致谢。

编辑:在下面添加了代码。


-> 登录
-> -> LoginViewController.swift

class LoginViewController: UIViewController {

    @IBOutlet weak var usernameTextField: CustomTextField!
    @IBOutlet weak var passwordTextField: CustomTextField!
    @IBOutlet weak var loginButton: UIButton!
    @IBOutlet weak var forgotPasswordButton: UIButton!
    @IBOutlet weak var navigationBar: UINavigationBar!

    override func viewWillAppear(_ animated: Bool) {
        UIApplication.shared.statusBarStyle = .lightContent
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // MARK: - IBActions
    @IBAction func loginPressed(sender: AnyObject) {
        usernameTextField.trimSpaces()

        let username = usernameTextField.text!
        let password = passwordTextField.text!

        Request.login(username, password)
    }
}

ACommonLibrary
-> 后端
-> -> Request.swift

public class Request {
    public class func login(_ username:String, _ password:String) {

    let headers: HTTPHeaders = [
        "Content-Type": "application/x-www-form-urlencoded"
    ]

    let parameters:Parameters = [
        "username": username,
        "password": password
    ]

    let endpoint = GlobalVariables.BaseURLString + "login"

    Alamofire.request(endpoint, method: .post, parameters: parameters, headers: headers)
    .responseJSON { response in
        switch response.result {
            case .success/*(let data)*/:
            if response.result.value != nil{
                let swiftyJsonVar = JSON(response.result.value!)

                let responseSuccess = swiftyJsonVar["success"]
                let responseMessage = swiftyJsonVar["error_message"]
                let responseSession = swiftyJsonVar["session_id"]
                let responseUserId = swiftyJsonVar["user_id"]

            if responseSession != JSON.null {
                GlobalVariables.Keychain["user_id"] = responseUserId.rawValue as? String
                GlobalVariables.Keychain["session_id"] =  responseSession.rawValue as? String
                try? GlobalVariables.Keychain.set(username, key: "username")

                if responseSuccess.boolValue {
                    let storyboard:UIStoryboard = UIStoryboard(name: "profile", bundle: nil)
                    let vc = storyboard.instantiateViewController(withIdentifier: "ProfileNavigation") as!     ProfileViewController
                    self.present(vc, animated: true, completion: nil)
                }else{
                    SCLAlertView().showNotice("Warning!", subTitle: responseMessage.stringValue)
                }
            }else{
                SCLAlertView().showError("Error logging in", subTitle: "There was an error while logging in     to your account. If this error persists, the server is down :D ")
            }
        }
        case .failure/*(let err)*/:
//          NSLog("------------------DATA START-------------------")
//          NSLog("Response String: (String(describing: err))")
            SCLAlertView().showError("Error logging in", subTitle: "There was an error while logging in to     your account. If this error persists, the server is down :D ")
//          NSLog("------------------DATA END-------------------")
        }
    }
}    

标签: iosswiftseguealamofireuistoryboard

解决方案


首先,您应该知道self在您尝试在类方法中执行的类方法中是不可访问loginRequests。您尝试做的事情有两种可能,如下所述。

  1. Requests不是 的子类UIViewController。只有一个UIViewController或其子类可以呈现另一个视图控制器。因此可以使用您的共享应用程序的keyWindowrootViewController。就是这样:

    if responseSuccess.boolValue {
        let storyboard:UIStoryboard = UIStoryboard(name: "profile", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "ProfileNavigation") as! ProfileViewController
        let rootVC = UIApplication.shared.keyWindow?.rootViewController
        rootVC?.present(vc, animated: true, completion: nil)
    } else {
        SCLAlertView().showNotice("Warning!", subTitle: responseMessage.stringValue)
    }
    
  2. 在进行异步网络调用的方法中使用闭包,就像在方法中所做的那样login。然后在闭包中执行 segues 和显示/呈现视图控制器。就是这样:

    public class Request {
    public class func login(_ username:String, _ password:String, withSuccess successHandler:@escaping (Bool) -> Void, andFailure failureHandler:@escaping (String) -> Void) {
    
        let headers: HTTPHeaders = ["Content-Type": "application/x-www-form-urlencoded"]
    
        let parameters:Parameters = ["username": username, "password": password]
    
        let endpoint = GlobalVariables.BaseURLString + "login"
    
        Alamofire.request(endpoint, method: .post, parameters: parameters, headers: headers)
            .responseJSON { response in
                switch response.result {
                case .success/*(let data)*/:
                    if response.result.value != nil{
                        let swiftyJsonVar = JSON(response.result.value!)
    
                        let responseSuccess = swiftyJsonVar["success"]
                        let responseMessage = swiftyJsonVar["error_message"]
                        let responseSession = swiftyJsonVar["session_id"]
                        let responseUserId = swiftyJsonVar["user_id"]
    
                        if responseSession != JSON.null {
                            GlobalVariables.Keychain["user_id"] = responseUserId.rawValue as? String
                            GlobalVariables.Keychain["session_id"] =  responseSession.rawValue as? String
                            try? GlobalVariables.Keychain.set(username, key: "username")
    
                            if responseSuccess.boolValue {
                                successHandler(true)
                            } else {
                                failureHandler(responseMessage.stringValue)
                            }
                        } else {
                            failureHandler("There was an error while logging in to your account. If this error persists, the server is down :D")
                        }
                    }
                case .failure/*(let err)*/:
                    failureHandler("There was an error while logging in to your account. If this error persists, the server is down :D")
                }
            }
        }
    }
    

    然后在LoginViewController

    @IBAction func loginPressed(sender: AnyObject) {
        usernameTextField.trimSpaces()
    
        let username = usernameTextField.text!
        let password = passwordTextField.text!
    
        Request.login(username,
                      password,
                      withSuccess: { (success) in
                        let vc = self.storyboard?.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
                        self.present(vc, animated: true, completion: nil)
        }) { (errorMsg) in
            SCLAlertView().showError("Error logging in", subTitle: errorMsg)
        }
    }
    

推荐阅读