从视图控制器的分离文件中呈现视图控制器
Present a view controller from a detached file from view controller
我有这个应用程序,它利用 Alamofire 将请求发送到后端,后端会吐出响应,并根据响应执行操作。我发现 Alamofire 代码对于我的项目来说太混乱了,我想将代码解析为一行代码。为此,我将 Alamofire 代码块放在我的一个自定义框架库中名为 Requests 的 class 中。每次我从后端收到响应时,我都想 运行 一个函数(不是问题),然后对下一个视图控制器(问题)执行 segue/present/push。
假设我有一个请求 class,其中包含一个接受用户名和密码参数的 login() 函数。调用此函数时的一行代码如下所示:Request.login(username, password)
,最后是 Request.logout()
,等等。可以在同一 Xcode 项目中的 ACommonLibrary 框架中找到此函数。这将 运行 Alamofire 代码发送请求,然后以 JSON 格式获得“已验证:true”的响应,根据该应用程序将 segue/present /push 到配置文件视图控制器.
我试着用一个布尔值来做这件事,如果我得到一个响应,一个变量将从 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
在 class 方法中不可访问,而你试图在 Requests
login
方法中执行 class .您尝试做的事情有两种可能,如下所述。
Requests
不是 UIViewController
的子 class。只有 UIViewController
或其子 class 可以呈现另一个视图控制器。因此可以利用共享应用程序的 keyWindow
和 rootViewController
。方法如下:
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)
}
在进行异步网络调用的方法中使用闭包,就像您在 login
方法中所做的那样。然后在闭包中执行 segues 和 show/present 视图控制器。方法如下:
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)
}
}
我有这个应用程序,它利用 Alamofire 将请求发送到后端,后端会吐出响应,并根据响应执行操作。我发现 Alamofire 代码对于我的项目来说太混乱了,我想将代码解析为一行代码。为此,我将 Alamofire 代码块放在我的一个自定义框架库中名为 Requests 的 class 中。每次我从后端收到响应时,我都想 运行 一个函数(不是问题),然后对下一个视图控制器(问题)执行 segue/present/push。
假设我有一个请求 class,其中包含一个接受用户名和密码参数的 login() 函数。调用此函数时的一行代码如下所示:Request.login(username, password)
,最后是 Request.logout()
,等等。可以在同一 Xcode 项目中的 ACommonLibrary 框架中找到此函数。这将 运行 Alamofire 代码发送请求,然后以 JSON 格式获得“已验证:true”的响应,根据该应用程序将 segue/present /push 到配置文件视图控制器.
我试着用一个布尔值来做这件事,如果我得到一个响应,一个变量将从 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
在 class 方法中不可访问,而你试图在 Requests
login
方法中执行 class .您尝试做的事情有两种可能,如下所述。
Requests
不是UIViewController
的子 class。只有UIViewController
或其子 class 可以呈现另一个视图控制器。因此可以利用共享应用程序的keyWindow
和rootViewController
。方法如下: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) }
在进行异步网络调用的方法中使用闭包,就像您在
login
方法中所做的那样。然后在闭包中执行 segues 和 show/present 视图控制器。方法如下: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) } }