I have an animating set of UIImageView\'s that represent a current value and continually keeps ticking upwards...ideally never stopping, also in the view is a scrollView or to a
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 displayLink
var displayLink: CADisplayLink?
// delegate your scrollview
self.scrollView.delegate = self
// start your anmiations
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.startTimer()
}
// animation block
@objc private func shakeStartButton() {...}
// your animation timer
private 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?