当前位置: 动力学知识库 > 问答 > 编程问答 >

Swift: How to loop through NSURLSession with different NSURL orderly?

问题描述:

Basically I want to loop through 4 web pages, obtaining 6 data from each page, having a total of 24 data in an array at the end of the loop, then display the last added data of that array (the 24th object in the array) / (the 6th data of the 4th web page) on message.text label.

Information:

i) The 4 web pages I want to loop through:

http://apims.doe.gov.my/apims/hourly1.php

http://apims.doe.gov.my/apims/hourly2.php

http://apims.doe.gov.my/apims/hourly3.php

http://apims.doe.gov.my/apims/hourly4.php

ii) The NSURLSession task to obtain the 6 data ("AQI1", "AQI2", "AQI3", "AQI4", "AQI5", "AQI6") from a page, and add into empty [String] array ("AQI"):

var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!

var cutCut = urlContent.componentsSeparatedByString("<td>Kota Tinggi</td>")

var cut = cutCut[1].componentsSeparatedByString("<b>")

var arr1 = cut[1].componentsSeparatedByString("</b>")

var AQI1 = arr1[0] as! String

var arr2 = cut[2].componentsSeparatedByString("</b>")

var AQI2 = arr2[0] as! String

var arr3 = cut[3].componentsSeparatedByString("</b>")

var AQI3 = arr3[0] as! String

var arr4 = cut[4].componentsSeparatedByString("</b>")

var AQI4 = arr4[0] as! String

var arr5 = cut[5].componentsSeparatedByString("</b>")

var AQI5 = arr5[0] as! String

var arr6 = cut[6].componentsSeparatedByString("</b>")

var AQI6 = arr6[0] as! String

self.AQI.extend([AQI1, AQI2, AQI3, AQI4, AQI5, AQI6])

iii) Var "taskerror" was created as a Boolean to check for unwanted errors in the task, and a Func ERROR( ) was created earlier to run if Var "taskerror" = true at the end.



Here is the whole code, which I've put under a IBAction button (I've created var AQI = [String] ( ) before the button):

AQI.removeAll(keepCapacity: true)

var pages = ["1", "2", "3", "4"]

for object in pages {

var url = NSURL(string: "http://apims.doe.gov.my/apims/hourly" + object + ".php")

var task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

var taskerror = false

if error == nil {

var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!

var cutCut = urlContent.componentsSeparatedByString("<td>Kota Tinggi</td>")

var cut = cutCut[1].componentsSeparatedByString("<b>")

var arr1 = cut[1].componentsSeparatedByString("</b>")

var AQI1 = arr1[0] as! String

var arr2 = cut[2].componentsSeparatedByString("</b>")

var AQI2 = arr2[0] as! String

var arr3 = cut[3].componentsSeparatedByString("</b>")

var AQI3 = arr3[0] as! String

var arr4 = cut[4].componentsSeparatedByString("</b>")

var AQI4 = arr4[0] as! String

var arr5 = cut[5].componentsSeparatedByString("</b>")

var AQI5 = arr5[0] as! String

var arr6 = cut[6].componentsSeparatedByString("</b>")

var AQI6 = arr6[0] as! String

self.AQI.extend([AQI1, AQI2, AQI3, AQI4, AQI5, AQI6])

} else {

taskerror = true

}

dispatch_async(dispatch_get_main_queue()) {

if taskerror {

self.ERROR()

} else {

if self.AQI.count == 24 {

self.message.text = self.AQI[23]

}

}

}

})

task.resume()

}

My problem is:

1) The sequence of running the task on the 4 URL is random, resulting in a random sequence of displaying the sets of 6 data in the array AQI, therefore the last (24th) object in the array AQI is not fixed, even though the last data from the 4th URL has not changed.

2) Using println(self.AQI) just before displaying AQI[23] on message.text, I can see that the set of 6 data is randomly sequenced.

3) Using println(object) just before var task shows that the loop is running through the URL "1", "2", "3", "4" accordingly. But if placed inside var task, it shows how the loop runs randomly (e.g. "2", "4", "3", "1"), resulting in the corresponding randomly arranged array AQI mentioned in (2).

My question is:

1) Why is the loop running randomly when in the task? (Not according to the set var pages = ["1", "2", "3", "4"] )

2) How do I make the task run orderly through the loop, so that the last object (24th) in the array AQI is always the same?

Note: I know I could just run the 4th URL if I want the last data, but I want to add some more code later on requiring all 24 data.

p.s. Is there a better way of doing what I want to do?

网友答案:

My answer below is not a direct solution to your problem, it's a follow-up to my comment, explaining why you get your responses in random order. I believe nonetheless it will very quickly allow you to find your solution. :)

Open the debug console, launch this code (adapted from yours) several times and watch the printed results.

var results = [Int:[String]]()

for index in 1...4 {
    println("Loop index: \(index)")

    var url = NSURL(string: "http://apims.doe.gov.my/apims/hourly\(index).php")

    var task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in

        var taskerror = false

        if error == nil {

            var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!
            var cutCut = urlContent.componentsSeparatedByString("<td>Kota Tinggi</td>")
            var cut = cutCut[1].componentsSeparatedByString("<b>")
            var arr1 = cut[1].componentsSeparatedByString("</b>")
            var AQI1 = arr1[0] as! String
            var arr2 = cut[2].componentsSeparatedByString("</b>")
            var AQI2 = arr2[0] as! String
            var arr3 = cut[3].componentsSeparatedByString("</b>")
            var AQI3 = arr3[0] as! String
            var arr4 = cut[4].componentsSeparatedByString("</b>")
            var AQI4 = arr4[0] as! String
            var arr5 = cut[5].componentsSeparatedByString("</b>")
            var AQI5 = arr5[0] as! String
            var arr6 = cut[6].componentsSeparatedByString("</b>")
            var AQI6 = arr6[0] as! String

            results[index] = [AQI1, AQI2, AQI3, AQI4, AQI5, AQI6]

        } else {
            taskerror = true
        }

        dispatch_async(dispatch_get_main_queue()) {
            if taskerror {
                println(taskerror)
            } else {
                println("Result index: \(index) - Content: \(results[index]!)")
            }
        }

    })

    task.resume()
}
  • 1:

  • 2:

Now you see that each task is indeed launched according to the loop index, in order, but the results are coming back asynchronously, depending on the time each task takes to get the data from the network. And it's not the same each time you launch your sequence, because of course the network speed is not constant.

In my example I used a Dictionary instead of an Array to store the results, it allowed me to show you that you get the right response for the right request, it's just that you get the results in random order, due to asynchronous nature of the tasks.

分享给朋友:
您可能感兴趣的文章:
随机阅读: