UIScrollView scroll event blocks UIView animation

后端 未结 2 1681
灰色年华
灰色年华 2021-02-04 14:41

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

相关标签:
2条回答
  • 2021-02-04 14:56

    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.

    0 讨论(0)
  • 2021-02-04 15:05

    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?

    0 讨论(0)
提交回复
热议问题