为什么此代码按此顺序执行?寻找流程的解释

时间:2016-10-25 15:11:59

标签: ios swift

在下面的代码中,我希望从数据库中提取一些属性 - 作为特定community成员的id。

我进行另一次API调用以获取这些社区成员的名称。

import UIKit

class ShowCommunityViewController: UIViewController {
    @IBOutlet weak var communityName: UILabel!
    var communityIsCalled: String?
    var comIds =  [String]()
    var communityId: Int?
    var communityPlayers =  [String]()
    var communityPlayerIds =  [String]()


    override func viewDidAppear(_ animated: Bool) {
        let myUrl = URL(string: "http://www.quasisquest.uk/KeepScore/specificCommunity.php?");
        var request = URLRequest(url:myUrl!);
        request.httpMethod = "POST";
        let postString = "id=\(comIds[communityId!])";
      //  print (postString)
        request.httpBody = postString.data(using: String.Encoding.utf8);

        let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in

            DispatchQueue.main.async
                {
                    if error != nil {
                        print("error=\(error)")
                        return
                    }

                    do{
                        let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
                     // print (json)
                       if let arr = json?["players"] as? [[String:String]] {
                            let players = arr.flatMap { $0["player_id"]!
                               // print(arr)
                          }
                        print ("one ",players)
                        self.communityPlayerIds = players
                        }

                    } catch{
                        print(error)
                    }
            }
        }
        task.resume()

        let myUrlTwo = URL(string: "http://www.quasisquest.uk/KeepScore/getPlayers.php?");
        var requestTwo = URLRequest(url:myUrlTwo!);
        requestTwo.httpMethod = "POST";
        let postStringTwo = "player_ids=\(self.communityPlayerIds)";
        print ("two ",postStringTwo)
        requestTwo.httpBody = postStringTwo.data(using: String.Encoding.utf8);

        let taskTwo = URLSession.shared.dataTask(with: requestTwo) { (data: Data?, response: URLResponse?, error: Error?) in

            DispatchQueue.main.async
                {

                    if error != nil {
                        print("error=\(error)")
                        return
                    }

                    do{
                        let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
                        // print (json)
                        if let arr = json?["player_names"] as? [[String:String]] {
                            let playerNames = arr.flatMap { $0["user_name"]!
                                // print(arr)

                            }
                            print ("three ", playerNames)
                        }



                    } catch{
                        print(error)
                    }
            }
        }
        taskTwo.resume()


    }


    override func viewDidLoad() {
        super.viewDidLoad()

        communityName.text = communityIsCalled

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

如果您注意到打印调试命令one, two, three的顺序。

它们实际上按two, one, three

的顺序执行

由于twoone之前执行,因此我的帖子字符串不需要player_ids来查找名称。

有人可以向我解释流程吗?

3 个答案:

答案 0 :(得分:4)

首先,让我们删除所有内容,只留下代码中的3个var $ = jQuery.noConflict();语句

print

let task = URLSession.shared.dataTask(with: request) { print("one") } task.resume() print("two") let taskTwo = URLSession.shared.dataTask(with: requestTwo) { print("three") } taskTwo.resume() 个任务以异步方式执行。当您调用URLSession时,它会将指令发送到另一个线程并立即跳转到下一行,而不等待task.resume()完成。与CPU的速度相比,网络请求速度极慢,因此几乎总是在task之前打印two

oneone的顺序不确定,具体取决于服务器响应哪一个更快。

答案 1 :(得分:0)

这是因为dataTask(request:)是异步的。这两个任务几乎立即启动,但在HTTP-Request完成时调用completionHandler。这可能会为每个请求花费不同的时间。

答案 2 :(得分:-1)

当您使用DispatchQueue.main.async时,您将作业添加到可以同时运行多个作业的队列中,每个作业都会在不同的时间内运行,因此其结果不一定在命令你在代码中拥有它们。

理论上,因为我不熟悉Swift的那一点:如果没有调用DispatchQueue.main.async那么它会按顺序执行它们但它会阻塞,代码会等待网络要求在继续之前完成,并且打印报表将按顺序排列。