NSOperationQueue completes all tasks in swift 3

I am trying to achieve NSOperationQueue by shutting down all tasks in swift 3. I am creating the demo code below and it works as expected.

func downloadTopStroiesDetails(){
    let operationQueue: OperationQueue = OperationQueue()
    let operation1 = BlockOperation() {
         print("BlockOperation1")
        for id in 0...5{
            operationQueue.addOperation(downloadArticle(index: id))
        }
        let operation2 = BlockOperation() {
            print("BlockOperation2")
        }
        operationQueue.addOperation(operation2)
    }
    operationQueue.addOperation(operation1)
}

func downloadArticle(index:Int) -> Operation {
    let operation: Operation = BlockOperation { () -> Void in
        print(index)
    }
    return operation
}
downloadTopStroiesDetails() // start calling 

      

Output:

BlockOperation1
0
1
2
3
4
5
BlockOperation2

      

But when I call the web API with Alamofire in the downloadArticle method it is different.

func downloadArticle(index:Int) -> Operation {
        let operation = BlockOperation(block: {
            RequestManager.networkManager.fetchFromNetworkwithID(articleid: index) { (response:Any ,sucess:Bool) in
                if sucess{
                      print(index)
                    //let art = article.init(json:(response as? json)!)!
                    // self.saveDataIntoCoreData(data: art)
                    //self.all_TopArticle.append(art)
                }
            };
        })
        return operation
    }

      

Now the output is:

BlockOperation1
BlockOperation2
0
1
2
3
4
5

      

What am I doing wrong here?

+3


source to share


1 answer


Your method downloadArticle

creates a blocking operation that completes immediately because it, in turn, performs an asynchronous operation.

You want the block not to go all the way until the asynchronous fetch completes. Using a semaphore would be one solution.

func downloadArticle(index:Int) -> Operation {
    let operation = BlockOperation(block: {
        let semaphore = DispatchSemaphore(value: 0)
        RequestManager.networkManager.fetchFromNetworkwithID(articleid: index) { (response:Any ,sucess:Bool) in
            if sucess{
                  print(index)
                //let art = article.init(json:(response as? json)!)!
                // self.saveDataIntoCoreData(data: art)
                //self.all_TopArticle.append(art)
            }
            semaphore.signal()
        };
        semaphore.wait()
    })
    return operation
}

      



Using this semaphore ensures that the operation does not actually complete until the network fetch is complete.

You might also want to make your order of queues of operations, rather than concurrent, to ensure that one operation can run concurrently. If that's what you want, set the operations queue maxConcurrentOperationCount

to 1

.

+8


source







All Articles