Swift OperationQueue for URLSession

I am an Android developer currently learning Swift. Can you help me with the OperationQueue please?

class ViewController: UIViewController {

     var movieArray :[Movie] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        let queue = OperationQueue()

        queue.maxConcurrentOperationCount = 1

        for index in 1...5
        {
            queue.addOperation {
            self.process(value: index)
            }
        }

    }

    func process(value:Int)
    {
        print("Start for: \(value)")

        let url = NSURL(string: URL_API+"\(value)")

        //fetching the data from the url
        URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in

            if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary
            {

                if let resultArray = jsonObj.value(forKey: "results") as? NSArray
                {
                    //Some Code...

                }

                print("Finish for: \(value)")
            }
        }).resume()

        print("End for: \(value)")
    }

}

What I expected to get is:

Start for: 1
Finish for: 1
End for: 1
Start for: 2
End for: 2
Finish for: 2
Start for: 3
Finish for: 3
End for: 3
Start for: 4
Finish for: 4
End for: 4
Start for: 5
Finish for: 5
End for: 5

What I got is:

Start for: 1
End for: 1
Start for: 2
End for: 2
Start for: 3
End for: 3
Start for: 4
End for: 4
Start for: 5
End for: 5
Finish for: 1
Finish for: 5
Finish for: 3
Finish for: 4
Finish for: 2

They not sequential, how can I make them so?

2 answers

  • answered 2019-06-25 08:48 vadian

    Although the operations are added sequentially it's not guaranteed that they finish in the same order because dataTask works asynchronously.

    The order Start - Finish - End will never happen anyway.
    Due to the asynchronous behavior the order of one data task is always Start - End – Finish.

    You need an asynchronous Operation described in this answer

    In the asynchronous Operation call finish() in the completion block of the data task.


    Note:

    Don't use NS... classes in Swift if there are native counterparts

    • NSURLURL
    • NSDictionary[String:Any]
    • NSArray[[String:Any]]

    And don't value(forKey which has a special functionality. Use key subscription dict["key"] or object(forKey. And the .allowFragments read option is pointless in Swift if the expected type is a collection type. Omit the parameter.

  • answered 2019-06-25 09:10 Prabhat Kasera

    You should have a look on the Managing Dependencies section in below document for your solution: https://developer.apple.com/documentation/foundation/operation or

    refer this thread NSOperationQueue serial FIFO queue

    either you have to make logic that when your first operation's finish/fail is called you should add the new operation to queue and reduce the task from the task stack.