在URLRequest dataTask

时间:2017-05-07 13:35:44

标签: ios swift xcode

我有一个类BaseViewController,它具有以下功能(AKSwiftSlideMenu):

func openViewControllerBasedOnIdentifier(_ strIdentifier:String){
    let destViewController : UIViewController = self.storyboard!.instantiateViewController(withIdentifier: strIdentifier)

    let topViewController : UIViewController = self.navigationController!.topViewController!

    if (topViewController.restorationIdentifier! == destViewController.restorationIdentifier!){
        print("Same VC")
    } else {
        self.navigationController!.pushViewController(destViewController, animated: true)
    }
}

有一个基于BaseViewController的视图控制器类可以进行登录检查,并包含一些控制器,包括2个文本字段控制器和一个按钮。以下代码附加到按钮的IBAction:

@IBAction func btn_login_pressed(_ sender: Any) { 
    //self.openViewControllerBasedOnIdentifier("logged")
    var request = URLRequest(url: URL(string: "https://someURL/login?Username="+(text_email.text)!+"&Password="+(text_password.text)!)!)
    request.httpMethod = "POST"
    let postString = ""
    request.httpBody = postString.data(using: .utf8)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data, error == nil else {                                                 // check for fundamental networking error
            print("error=\(String(describing: error))")
            return
        }

        if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {           // check for http errors
            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(String(describing: response))")
        }

        let responseString = String(data: data, encoding: .utf8)
        let dict = self.convertToDictionary(text: responseString!)
        let status:Int = dict?["Status"] as! Int

        if(status==0){
        print("fail")
        } else {
        self.openViewControllerBasedOnIdentifier("logged")
        }  
    }
    task.resume()
    //self.openViewControllerBasedOnIdentifier("logged")
 }

如果我在任务之前或在task.resume()之后使用self.openViewControllerBasedOnIdentifier,则一切正常,应用程序将打开新的视图控制器。另一方面,当我尝试在接收在线数据后使用该功能时,我也没有得到构建错误。代码运行,访问在线数据。 Dict得到它的价值。然后有很多等待,我在输出中得到以下消息:

2017-05-07 16:27:25.301 myApp [9788:3330252]此应用程序在从主线程访问引擎后从后台线程修改autolayout引擎。这可能导致引擎损坏和奇怪的崩溃。

有时会加载新视图,有时会失败。

另一方面,在获取在线登录数据之前,在task.resume()行之后写的东西似乎发生了。

所以我的问题是如何在获取在线数据后访问self.openViewControllerBasedOnIdentifier函数。

非常感谢任何帮助

1 个答案:

答案 0 :(得分:2)

确保所有UI工作都在主线程上完成。尝试将代码包装在调度块中以使用主线程

user=> (ancestors clojure.lang.PersistentVector)
#{clojure.lang.IEditableCollection clojure.lang.ILookup 
  java.util.concurrent.Callable java.lang.Runnable clojure.lang.IMeta 
  java.lang.Comparable clojure.lang.IReduceInit
  clojure.lang.IPersistentCollection clojure.lang.IHashEq java.lang.Iterable 
  clojure.lang.IReduce java.util.List clojure.lang.AFn clojure.lang.Indexed 
  clojure.lang.Sequential clojure.lang.IPersistentStack java.io.Serializable 
  clojure.lang.Reversible clojure.lang.Counted java.util.Collection 
  java.util.RandomAccess java.lang.Object clojure.lang.Seqable 
  clojure.lang.Associative clojure.lang.APersistentVector 
  clojure.lang.IKVReduce clojure.lang.IPersistentVector clojure.lang.IObj 
  clojure.lang.IFn}

当您发出网络请求时,它会在后台线程上异步运行。因此,当您收到响应并希望对您的用户界面执行某些操作时,您需要确保在主线程上完成此操作。

因为网络请求是异步的并且在后台线程上运行。您会注意到task.resume之前和之后的代码通常会在您获得响应之前运行,例如:

DispatchQueue.main.async {
    // init your views here
    let destViewController : UIViewController = self.storyboard!.instantiateViewController(withIdentifier: strIdentifier)

    let topViewController : UIViewController =     self.navigationController!.topViewController!

    if (topViewController.restorationIdentifier! == destViewController.restorationIdentifier!){
        print("Same VC")
    } else {
        self.navigationController!.pushViewController(destViewController, animated: true)
    }
}

此处的预期输出为:

  

之前的异步

     

后异步

     

收到回复