1

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?

Dim
  • 4,527
  • 15
  • 80
  • 139

2 Answers2

2

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.

vadian
  • 274,689
  • 30
  • 353
  • 361
0

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.

Prabhat Kasera
  • 1,129
  • 11
  • 28