我有一个收集用户名和密码的登录页面。提交时,它会发送到数据库以检索我们的服务器访问密钥。我使用session.dataTask通过一个异步JSON POST来实现这一点。当我检索JSON对象时,我从中解析出键。我想把它传递到下一个页面,检索一个firebase令牌,然后将这两个数据发送回服务器进行DB存储。我已经创建了一个“prepare for segue”函数来收集变量并将其传递给下一页的变量。我相信我没有正确设置事件序列,或者数据没有从异步容器中生成。有人能看看这两个文件,看看我哪里弄错了吗?
这是我在进行REST web服务调用后要离开的第一页。。。
登录代码.swift:
import UIKit
class LoginVC: UIViewController {
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var validationBox: UITextView!
@IBAction func logInAction(_ sender: UIButton) {
guard let user = username.text, !user.isEmpty else {
validationBox.text = "Please enter valid credentials"
return
}
guard let pass = password.text, !pass.isEmpty else {
validationBox.text = "Please enter valid credentials"
return
}
let params = ["sUser": username.text!, "sPass": password.text!]
let url = URL(string: "restWebServiceURL")!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else { return }
guard let data = data else { return }
do {
if let parsedJSON = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
let parsedData = parsedJSON["d"] as! [String:Any]
let key = parsedData["key"] as! String
DispatchQueue.main.async {
print(key)
self.performSegue(withIdentifier: "FirebaseVC", sender: key)
}
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}
func sayHello() {
print("Hello!")
}
func sayGoodbye() {
print("Goodbye!")
}
override func viewDidLoad() {
super.viewDidLoad()
validationBox.text = "Ready..."
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let FirebaseInit = segue.destination as? FirebaseVC {
if let sKey = sender as? String {
print("prepare - " + sKey)
FirebaseInit.sessionKey = sKey
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
这是我想去的网页,以接收数据访问密钥。。。
FirebaseVC.swift公司:
import UIKit
class FirebaseVC: UIViewController {
private var _sessionKey = String()
var sessionKey : String {
get { return _sessionKey }
set { _sessionKey = newValue }
}
@IBOutlet weak var sessionKeyTestBox: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
print(_sessionKey)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
请随意建议一种更好的方式将数据传递到下一页。谢谢。。。
最佳答案
事实证明,我的假设是正确的,事件链是关闭的。按照@achrefGassoumi建议的模型,我将datatask移到了这里的单例服务:
import Foundation
struct CallWebService {
static let sharedInstance = CallWebService()
func logInToCaduceus(u: String, p: String, completion: @escaping (_ sKey: String) -> ()) {
let params = ["sUser": u, "sPass": p]
let url = URL(string: "https://telemed.caduceususa.com/ws/telemed.asmx/telemedLogin")!
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
do {
request.httpBody = try JSONSerialization.data(withJSONObject: params, options: .prettyPrinted)
} catch let error {
print(error.localizedDescription)
}
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else { return }
guard let data = data else { return }
do {
if let parsedJSON = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
let parsedData = parsedJSON["d"] as! [String:Any]
let key = parsedData["key"] as! String
DispatchQueue.main.async {
completion(key)
}
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}
}
我的两个控制器是这样的:
罗金维克
import UIKit
class LoginVC: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.destination.isKind(of: FirebaseVC.self)) {
let vc = segue.destination as! FirebaseVC
if let sKey = sender as? String {
vc.sessionKey = sKey
}
}
}
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var validationBox: UITextView!
@IBAction func logInAction(_ sender: UIButton) {
guard let user = username.text, !user.isEmpty else {
validationBox.text = "Please enter valid credentials"
return
}
guard let pass = password.text, !pass.isEmpty else {
validationBox.text = "Please enter valid credentials"
return
}
CallWebService.sharedInstance.logInToCaduceus(u: username.text!, p: password.text!, completion: {(sessionKey: String) -> Void in
print(sessionKey)
self.performSegue(withIdentifier: "FirebaseVC", sender: sessionKey)
}
)
}
override func viewDidLoad() {
super.viewDidLoad()
//validationBox.textAlignment = .center
validationBox.text = "Ready..."
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
以及接收到的FirebaseVC
import UIKit
class FirebaseVC: UIViewController {
private var _sessionKey = String()
var sessionKey : String {
get { return _sessionKey }
set { _sessionKey = newValue }
}
@IBOutlet weak var sessionKeyTestBox: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
sessionKeyTestBox.text = _sessionKey
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
请原谅我的(非swift)Javascript术语,但本质上我将数据调用移到了一个服务中,然后将回调方法与completion方法放在服务中,以确保在接收并解析数据之前性能不会触发。因此,当我向服务器提交登录表单数据时,segue在异步调用完成之前不会启动。