从视图控制器分离的文件中呈现视图控制器



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

假设我有一个Request类,它包含一个login((函数,该函数接受用户名和密码参数。调用此函数时的单行代码如下:Request.login(username, password),最终为Request.logout()等。此函数可以在同一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"不能用于类型"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-------------------")
}
}
}    

首先,您应该知道self在类方法中是不可访问的,而您试图在Requests类的login方法中这样做。你想做的事情有两种可能,如下所述。

  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)
    }
    }
    

最新更新