orange_juice
orange_juice

Reputation: 191

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.

Upvotes: 0

Views: 725

Answers (1)

TheAppMentor
TheAppMentor

Reputation: 1099

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()

Upvotes: 2

Related Questions