Search code examples
swiftasynchronousdispatch-queue

Create a waiting queue for executing an animation


I am currently working on a swift animation. This animation gets triggered by an another function in unsteady time intervals (connected to a server). The animation takes 2 seconds to finish but its possible that it gets triggered before it has finished. Thats why I was thinking about creating a waiting queue which stores the triggering events until the animation is completed and can be restarted. So on the one hand side I have to lock the animation function until its ready again and one the other I need some kind of storage for the incoming events in the meantime. I was already thinking about dispatch groups but couldnt figure out how I could use them. I would be really happy about any input in which direction I could go to solve this problem.

Triggering function:

private func subscribeToNewBLock() {
        DispatchQueue.global(qos:.userInteractive).async {
            watchForNewBlock() {result in
                switch result {
                case .Failure:
                    return
                case .Success(let result):
                    //Animation function
                    self.moveBlocksDown(blockNumber: result)
                    //Recursive call to keep listening for new blocks
                    self.subscribeToNewBLock()
                }
            }
       }
}

Solution

  • You may try to make your animation queue as like below example

    var results = [Int]()
    var isAnimating = false
    
    private func subscribeToNewBLock() {
        DispatchQueue.global(qos:.userInteractive).async {
            watchForNewBlock() {result in
                switch result {
                case .Failure:
                    return
                case .Success(let result):
    
                    //Call your UI operations in main thread
                    DispatchQueue.main.async {
    
                        self.results.append(result)
                        //Animation function
                        self.moveBlocksDown()
    
                        //Recursive call to keep listening for new blocks
                        self.subscribeToNewBLock()
                    }
                }
            }
        }
    }
    
    private func moveBlocksDown() {
    
        guard isAnimating == false && results.count > 0 else {
    
            return
        }
    
        self.moveBlocksDown(blockNumber: results.first!)
    
    }
    
    private func moveBlocksDown(blockNumber:Int){
    
        isAnimating = true
    
        UIView.animate(withDuration: 2.0, animations: {
    
            //Animation code goes here
    
        }) { (completed) in
    
            if completed{
    
                //Add follwing code in place of animation completed(May be in completion handler)
                self.isAnimating = false
                self.results = self.results.filter{$0 != blockNumber} //Remove already animated blockNumber
                self.moveBlocksDown() //Call moveBlocksDown function to check if anything pending in queue
            }
        }
    }