orange_juice orange_juice - 1 month ago 11
iOS Question

Nested asynchronous blocks of code in Swift

I am trying to nest a

NSTimer.scheduledTimerWithTimeInterval
call inside of an asynchronous
NSURLSession.sharedSession().dataTaskWithRequest
in Swift 2.0, but the code block inside of the
test
does not seem to get evaluated.

For example:

class testc{

@objc func test()
{
print("hello");
}

func loop()
{
if let url = NSURL(string : "https://www.google.com")
{
let url_req = NSURLRequest(URL: url);

let task = NSURLSession.sharedSession().dataTaskWithRequest(url_req)
{ data, response, error in

let timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(testc.test), userInfo: nil, repeats: true)

}

task.resume()

}


}
}


If we initialize this class and run
loop
nothing happens, the function
test
was never evaluated.

Answer

You need two changes to your code.

After creating the dataTask. You need to ask it to resume() to send the request. The timer needs to be called on the main thread.

In your case, the dataTask is an asynchrnous task that runs on a background thread. In the implementation below, we are jumping back to the main thread to fire the timer.

I have added a counter to verify if the timer is firing repeatedly.

See updated code below.

    class testc{

    static var counter : Int = 0

    @objc func test()
    {   testc.counter++
        print("hello -> \(testc.counter)");
    }

    func loop()
    {
        if let url = NSURL(string : "https://www.google.com")
        {
            let url_req = NSURLRequest(URL: url);

            let task = NSURLSession.sharedSession().dataTaskWithRequest(url_req){ data, response, error in

                dispatch_async(dispatch_get_main_queue(), { 
                    self.setupTimer()
                })

            }.resume()
        }
    }

    func setupTimer() {
        let timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(testc.test), userInfo: nil, repeats: true)
    }

}


let theBoy = testc()

theBoy.loop()