You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Swift:如何实现无停顿的动态平滑视图连续动画

Fixing the Stutter Between Consecutive iOS Swift Animations

Hey there! I’ve run into this exact animation pause issue before with Swift UIKit animations, so I know how frustrating that tiny stutter can be when trying to chain animations that only differ by their end point. Let’s break down why it’s happening and how to fix it.

Why the Pause Happens

The problem with your current completionHandler approach is that when a standard UIView.animate block finishes, UIKit immediately snaps the view’s property to its final value before calling the completion handler. Then, starting a new animation from that final value introduces a tiny delay as the system queues up the next animation cycle—hence the stutter.

UIViewPropertyAnimator gives you far more control over animation states, making it perfect for smooth consecutive animations. You can pause, resume, or even modify animations mid-cycle, and restart them from the exact current visual state of the view.

Here’s an implementation example:

// Keep a reference to the animator so we can control it
var continuousAnimator: UIViewPropertyAnimator?

func startSmoothAnimationCycle() {
    // Define your animation duration and curve (adjust as needed)
    continuousAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear) {
        // Set the view's next target position
        self.animatedView.center = self.getNextTargetPosition()
    }
    
    // Add a completion handler to restart the animation if needed
    continuousAnimator?.addCompletion { [weak self] position in
        guard let self = self else { return }
        
        // Only restart if the animation completed normally and our condition is met
        if position == .end, self.shouldKeepAnimating() {
            // Stop the current animator without jumping to the end
            self.continuousAnimator?.stopAnimation(false)
            // Finish the animation at its current state to preserve progress
            self.continuousAnimator?.finishAnimation(at: .current)
            // Start the next animation cycle
            self.startSmoothAnimationCycle()
        }
    }
    
    // Kick off the first animation
    continuousAnimator?.startAnimation()
}

// Helper: Return your next target position (customize this logic)
func getNextTargetPosition() -> CGPoint {
    // Example: Random position within the parent view bounds
    let x = CGFloat.random(in: 50...(self.view.bounds.width - 50))
    let y = CGFloat.random(in: 50...(self.view.bounds.height - 50))
    return CGPoint(x: x, y: y)
}

// Helper: Your condition to keep animating (customize this)
func shouldKeepAnimating() -> Bool {
    // Example: Keep animating indefinitely
    return true
}

Why This Works

  • stopAnimation(false) prevents the animator from jumping to the final value immediately.
  • finishAnimation(at: .current) locks in the view’s current animated state (the position it’s visually in on screen).
  • The next animation starts from that exact visual state, eliminating any stutter between cycles.

Solution 2: Adjust Standard UIView.animate for Smoother Chaining

If you prefer sticking with standard UIView.animate, you can fix the stutter by syncing the view’s actual property to its on-screen animated state before starting the next animation.

Here’s how:

func animateConsecutively() {
    UIView.animate(withDuration: 1.0, animations: {
        self.animatedView.center = self.getNextTargetPosition()
    }) { [weak self] animationFinished in
        guard let self = self, animationFinished, self.shouldKeepAnimating() else { return }
        
        // Get the view's current on-screen position (from the animation layer)
        if let currentVisibleCenter = self.animatedView.layer.presentation()?.center {
            // Update the view's actual property to match its visible state
            self.animatedView.center = currentVisibleCenter
        }
        
        // Start the next animation
        self.animateConsecutively()
    }
}

Why This Works

The layer.presentation() gives you the visual state of the view during the animation (not the final value that UIKit sets after completion). By updating the view’s actual center property to this value before starting the next animation, you eliminate the snap-to-final-value delay that causes the stutter.

Final Notes

  • For most continuous animation use cases, UIViewPropertyAnimator is the better choice—it’s more flexible and gives you finer control over animation behavior.
  • Make sure to use [weak self] in completion handlers to avoid retain cycles.

内容的提问来源于stack exchange,提问作者Masashi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:57:24