UIScrollView scroll event blocks UIView animation UIScrollView scroll event blocks UIView animation multithreading multithreading

UIScrollView scroll event blocks UIView animation


As danypata pointed out in my comments via this thread My custom UI elements are not being updated while UIScrollView is scrolled It has something to do with the NStimer thread rather than the animation thread, or possibly both if someone can clarify. In any case when scrolling it seems all scroll events get exclusive use of the main loop, the solution is to put the timer you are using to do your animation into the same loop mode which is UITrackingLoopMode so it too get's use of the main loop when scrolling and...

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:foreveryNseconds target:self selector:@selector(AscendDigit:) userInfo:dict repeats:YES];[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

Tada.


There is another way to control your animations during UIScrollview scroll with scrollView delegate methods; start your animations with Timer than stop the timer in scrollViewWillBeginDragging method and continue to your animations with displayLink etc. for example :

// Declare an displayLinkvar displayLink: CADisplayLink?// delegate your scrollviewself.scrollView.delegate = self// start your anmiationsoverride func viewDidAppear(_ animated: Bool) {    super.viewDidAppear(animated)    self.startTimer()}// animation block@objc private func shakeStartButton() {...}// your animation timerprivate func startTimer() {    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.shakeStartButton), userInfo: nil, repeats: true)    timer?.fire()}private func startDisplayLinkIfNeeded() {    if displayLink == nil {        self.displayLink = CADisplayLink(target: self, selector: #selector(self.shakeStartButton))        displayLink?.add(to: .main, forMode: .tracking)        // Render frame only one time in second        displayLink?.preferredFramesPerSecond = 1    }}private func stopDisplayLink() {    displayLink?.invalidate()    displayLink = nil}extension YourViewController: UIScrollViewDelegate { func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {    self.timer?.invalidate()    self.startDisplayLinkIfNeeded() } func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {    if !decelerate {        self.stopDisplayLink()        self.startTimer()    } }  func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {    self.stopDisplayLink()    self.startTimer() }}

Note: This is litte bit longer than @gehan answer but it may help with other things also?