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

如何手动停止Lottie动画?解决XCode中Lottie后台运行及内存问题

Hey there, let's work through your Lottie animation issues one by one. I'll break down the problems in your current code and provide a fixed version with clear explanations.

Key Issues in Your Current Implementation
  1. Repeated AnimationView Initialization: Every time you tap the popup button, you create a new AnimationView instance and add it to the view, leaving old instances unremoved—this causes memory bloat over time.
  2. Unmanaged Animation State: When navigating away from the view controller, the animation keeps running in the background, leading to unnecessary memory usage and unexpected restarts when you return.
  3. No Controlled Stop Mechanism: There's no built-in logic to halt the animation after a specific duration.
Solutions & Fixed Code

Step 1: Reuse AnimationView Instead of Recreating It

Instead of initializing a new AnimationView in the animation() method, use the existing popupView outlet you've already set up. This prevents memory leaks from orphaned animation instances.

Step 2: Manage Animation in View Lifecycle Methods

Pause the animation when the view disappears, and clean up resources when the view controller is destroyed to stop background execution and free memory.

Step 3: Add Timed Stop Logic

Use a delayed dispatch call to stop the animation after your desired duration (e.g., 3 seconds in the example below).

Here's the revised code:

import UIKit
import Lottie

class CoffeeSpecialFortunePageVC: UIViewController {
    @IBAction func PopUpIn(_ sender: Any) {
        animateIn(desiredView: PopupBlur)
        animateIn(desiredView: popupView)
        startAnimation()
    }
    
    @IBAction func SuccesBtn(_ sender: UIView) {
        stopAnimation()
        animateOut(desiredView: PopupBlur)
        animateOut(desiredView: popupView)
    }
    
    @IBOutlet var popupView: AnimationView!
    @IBOutlet var PopupBlur: UIVisualEffectView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.purple
        PopupBlur.bounds = self.view.bounds
        popupView.bounds = CGRect(x: 0, y: 0, width: self.view.bounds.width * 0.9, height: self.view.bounds.height * 0.4)
        
        // Initialize Lottie animation once on view load
        setupAnimation()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // Pause animation when leaving the view to stop background execution
        stopAnimation()
        
        // Clean up resources if we're navigating away from this VC entirely
        if isMovingFromParent {
            popupView.removeFromSuperview()
            popupView = nil
        }
    }
    
    private func setupAnimation() {
        // Reuse the existing popupView outlet
        popupView.animation = Animation.named("check1")
        popupView.contentMode = .scaleAspectFit
        popupView.frame = CGRect(x: 0, y: 0, width: 350, height: 350)
        popupView.center = view.center
        popupView.stop() // Start with animation paused
    }
    
    private func startAnimation() {
        // Play animation once (use .loop if you need repeated playback)
        popupView.play(loopMode: .playOnce) { finished in
            if finished {
                print("Animation completed naturally")
            }
        }
        
        // Stop animation after 3 seconds (adjust the duration as needed)
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
            self?.stopAnimation()
        }
    }
    
    private func stopAnimation() {
        guard popupView.isAnimationPlaying else { return }
        popupView.stop()
    }
    
    func animateIn(desiredView: UIView) {
        guard desiredView.superview == nil else { return } // Avoid duplicate subviews
        let backgroundView = self.view!
        backgroundView.addSubview(desiredView)
        
        desiredView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
        desiredView.alpha = 0
        desiredView.center = backgroundView.center
        
        UIView.animate(withDuration: 0.3) {
            desiredView.transform = .identity
            desiredView.alpha = 1
        }
    }
    
    func animateOut(desiredView: UIView) {
        UIView.animate(withDuration: 0.3, animations: {
            desiredView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
            desiredView.alpha = 0
        }, completion: { _ in
            desiredView.removeFromSuperview()
            // Ensure animation stops if we're removing the AnimationView
            (desiredView as? AnimationView)?.stop()
        })
    }
}

Key Improvements Explained

  • Reusable Animation Instance: The setupAnimation() method initializes the animation once, so we don't create redundant AnimationView objects that waste memory.
  • Lifecycle Awareness: viewWillDisappear pauses the animation and cleans up resources when leaving the view, preventing background execution and memory leaks.
  • Timed Stop: DispatchQueue.main.asyncAfter triggers the animation stop after your specified duration—just change the +3 to your desired number of seconds.
  • Weak Self in Closures: Prevents retain cycles that would keep the view controller in memory unnecessarily.
  • Duplicate View Prevention: Checks if a view is already in the hierarchy before adding it, avoiding messy view stacks and extra memory usage.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:51:05