从 IBAction 调用的 dispatchqueue.main.async 中跳过了 Https 请求

Posted

技术标签:

【中文标题】从 IBAction 调用的 dispatchqueue.main.async 中跳过了 Https 请求【英文标题】:Https Request skipped in dispatchqueue.main.async called from IBAction 【发布时间】:2021-02-14 02:16:43 【问题描述】:

从 IBAction 调用时,会跳过获取 json 和解码的请求!但如果它是在 viewDidLoad 中制作的,它就可以工作。谁能启发我并帮助我如何解决这个问题?提前谢谢!

class LoginViewController:UIViewController 

    @IBOutlet weak var login_id_field: UITextField!
    @IBOutlet weak var login_pw_field: UITextField!


    var loginData = [LoginData]()
    var storeData = [StoreData]()
    So below part in viewDidLoad() is working fine,

    override func viewDidLoad() 
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
    let param2 = ["login": self.login_id_field.text!]
    let url2 = "http://dev.purejoin.com/PJPI/login.php"
    print("HI")
    
    DispatchQueue.main.async 
        let headers: HTTPHeaders = [
            "Accept": "text/html",
            "Content-Type" : "application/x-www-form-urlencoded"
        ]
        AF.request(url2, method: .post, parameters: param2, encoding: URLEncoding.httpBody, headers: headers).responseString  response in
            #if DEBUG
            let request = response.request
            NSLog("Request: \(request!.httpMethod!) - \(request!.url!.absoluteString)\n\(request!.httpBody.map  body in String(data: body, encoding: .utf8) ?? ""  ?? "")")
            switch response.result 
            case .success(let value):
                print("Response with content \(value)")
            case .failure(let error):
                print("Response with error: \(error as NSError): \(response.data ?? Data())")
            
            #endif
        
    


但是下面的这里不起作用。 Dispatchqueue.main.async 刚刚被跳过?至少看起来是这样的。

@IBAction func login_button(_ sender: Any) 
    //Check for email field that is too short or just didn't get any input
    if (self.login_id_field.text!.count < 7 ) 
        let alert = UIAlertController(title: "Invalid Email", message: "Please Check Your Email", preferredStyle: .alert)
        let ok = UIAlertAction (title: "OK", style: UIAlertAction.Style.cancel, handler: nil)
        alert.addAction(ok)
        self.present(alert, animated: true, completion: nil)
    
    //query
    else 
        let param2 = ["login": self.login_id_field.text!]
        let url2 = "http://dev.purejoin.com/PJPI/login.php"
        print("HI")
        
        DispatchQueue.main.async 
            
            let headers: HTTPHeaders = [
                "Accept": "text/html",
                "Content-Type" : "application/x-www-form-urlencoded"
            ]
            AF.request(url2, method: .post, parameters: param2, encoding: URLEncoding.httpBody, headers: headers).responseString  response in                        #if DEBUG
            let request = response.request
            NSLog("Request: \(request!.httpMethod!) - \(request!.url!.absoluteString)\n\(request!.httpBody.map  body in String(data: body, encoding: .utf8) ?? ""  ?? "")")
            switch response.result 
            case .success(let value):
                print("Response with content \(value)")
            case .failure(let error):
                print("Response with error: \(error as NSError): \(response.data ?? Data())")
            
            #endif
            
        
        
        
        
        //MD5
        let md5 = MD5(self.login_pw_field.text!)
        print (self.loginData)
        if (md5 == String(self.loginData[0].user_password)) 
            //OPEN SEGUE
            let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyBoard.instantiateViewController(withIdentifier: "selectStore") as! SelectStoreViewController
            self.present(vc, animated: true, completion: nil)
         else 
            let alert = UIAlertController(title: "Wrong Password", message: "Please Check Your Password", preferredStyle: .alert)
            let ok = UIAlertAction (title: "OK", style: UIAlertAction.Style.cancel, handler: nil)
            alert.addAction(ok)
            self.present(alert, animated: true, completion: nil)
        
        
    
  

【问题讨论】:

首先:永远不要在DispatchQueue.main上运行任何网络请求;将它直接放在 viewDidLoad 或任何 IBAction 中也是一个非常糟糕的设计。但是你也可以在几个地方放置断点(例如在 DispatchQueue 中,看看它是否到达那里 那你建议我把 dispatchqueue.main 放在哪里? 【参考方案1】:

DispatchQueue.main.async enqueue 这样的异步调用在队列上工作,然后继续执行,无需等待完成。有多种方法可以解决这个问题,但幸运的是您不需要其中任何一种:您无需致电 DispatchQueue.main.async

相反,只需发出您的网络请求,Alamofire 就会回调主队列(默认情况下)以执行您的响应处理程序的内容(在本例中为 responseString)。从表面上看,您需要将网络调用之后的逻辑移动到您的响应处理程序中,因为它取决于网络调用的结果。

【讨论】:

以上是关于从 IBAction 调用的 dispatchqueue.main.async 中跳过了 Https 请求的主要内容,如果未能解决你的问题,请参考以下文章

从 xib 内的按钮单击调用 IBAction 时出错

当从同一个组件调用时,两个 IBAction 触发的顺序是啥?

从 NSTimer 函数调用 UIButton @IBAction [关闭]

从 IBAction 调用的 dispatchqueue.main.async 中跳过了 Https 请求

我可以从 IBAction 中调用 UIAlertController [重复]

从 IBAction 方法调用 AudioServicesPlaySystemSound 声音时听不到声音