RDowns RDowns - 1 month ago 6
Swift Question

Why does this code execute in this order? Looking for explanation of process flow

In the following code I am looking to pull some attributes from a database - id's who are members of a particular

community
.

I make another API call to fetch the names of those community members.

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.
}
}


If you note the order of the print debug commands
one, two, three
.

They actually execute in order of
two, one, three
.

Because
two
is executing before
one
my Post String does not have the
player_ids
required to look up the names.

Could someone please explain the process flow to me?

Answer

First, let's strip away everything, leaving just the 3 print statements in your code

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 tasks are executed asynchronously. When you call task.resume(), it sends the instructions to another thread and immediately jumps to the next line, without waiting for the task to complete. Network requests are extremely slow compared to the CPU's speed so it will almost always print two before one.

The order of one and three are uncertain, depending on which one is faster for the server to respond.

Comments