FLEXTool / FLEX

An in-app debugging and exploration tool for iOS

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CATransaction.setCompletionBlock's closure is not called.

devikkim opened this issue · comments

Environment

  • Platform+version: iOS 14.3
  • FLEX version: 4.4.0

Bug Report


When i turn on a FLEX and then touch some menu (like menu, views, select, have to touch some menu. if don't touch menu then no problem.), CATransaction.setCompletionBlock's closure is not called

But, when i turn on a FLEX and then don't touch anythings, CATransaction.setCompletionBlock's closure is called.

This situation only occurs after touch the FLEX menu.

I used CATransaction to make particle animation because, CAEmitterLayer can't detect end time of animation.


Below is an example code.

private class Layer: CAEmitterLayer {
// custom CAEmitterLayer to particle animation
... 
}

func emit(duration: TimeInterval = 1, completion: (() -> Void)? = nil) {
    let layer = Layer()
    self.layer.addSublayer(layer)
        
    layer.beginTime = CACurrentMediaTime()
    layer.birthRate = 1.0
        
    CATransaction.begin()
    CATransaction.setCompletionBlock {[weak self] in  // <-- problem closure
            guard let self = self else { return }
            
            let transition = CATransition()
            transition.delegate = self
            layer.add(transition, forKey: nil)
            
            layer.opacity = 0
    }
    CATransaction.commit() // If you take a break point this line, then CATransaction.setCompletionBlock 's closure is called.
}

// CAAnimationDelegate
func animationDidStop(_ animation: CAAnimation, finished flag: Bool) {
    self.completion?()
}

Why is CATransaction.setCompletionBlock's closure not called?
I don't understand these situation.. please help me..

You can test these situation using below sample app.
FireworkAnimation.zip

I honestly have no idea either; it's probably some UIKit bug. This is quite peculiar. I noticed that if you set a breakpoint right on CATransaction.begin() and immediately continue when it hits the breakpoint, the completion handler is still called. It's some kind of race condition.

Related: https://stackoverflow.com/questions/27470130/catransaction-completion-block-never-fires

Closing this as I don't think I'll be able to fix it :/ Feel free to reopen it if you figure out what's wrong