Repository: airbnb/lottie-ios
File: Sources/Public/Animation/LottieAnimationLayer.swift (Swift)

Code before:
  /// does not need to update playback code.
  ///
  /// Returns the Frame Time for the marker named. Returns nil if no marker found.
  public func frameTime(forMarker named: String) -> AnimationFrameTime? {
    guard let animation else {
      return nil
    }
    return animation.frameTime(forMarker: named)
  }

  /// Markers are a way to describe a point in time and a duration by a key name.
  ///
  /// Markers are encoded into animation JSON. By using markers a designer can mark
  /// playback points for a developer to use without having to worry about keeping
  /// track of animation frames. If the animation file is updated, the developer
  /// does not need to update playback code.
  ///
  /// - Returns: The duration frame time for the marker, or `nil` if no marker found.
  public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? {
    guard let animation else {
      return nil
    }
    return animation.durationFrameTime(forMarker: named)
  }

  public func updateAnimationForBackgroundState(forWindow: Bool = false) {
    if let currentContext = animationContext {
      let behavior = forWindow ? (windowBackgroundBehavior ?? backgroundBehavior) : backgroundBehavior
      switch behavior {
      case .stop:
        removeCurrentAnimation()
        updateAnimationFrame(currentContext.playFrom)

      case .pause:
        removeCurrentAnimation()

      case .pauseAndRestore:
        currentContext.closure.ignoreDelegate = true
        removeCurrentAnimation()
        /// Keep the stale context around for when the app enters the foreground.
        animationContext = currentContext

      case .forceFinish:
        removeCurrentAnimation()
        updateAnimationFrame(currentContext.playTo)

      case .continuePlaying:
        break
      }
    }
  }

Review comment (suggestion):
What if we generalize this further with:

```suggestion
  public func updateAnimationForBackgroundState(backgroundBehavior: LottieBackgroundBehavior = nil) {
```

Code after:
  /// - Returns: The duration frame time for the marker, or `nil` if no marker found.
  public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? {
    guard let animation else {
      return nil
    }
    return animation.durationFrameTime(forMarker: named)
  }

  public func updateAnimationForBackgroundState(backgroundBehavior: LottieBackgroundBehavior? = nil) {
    if let currentContext = animationContext {
      let effectiveBehavior = backgroundBehavior ?? self.backgroundBehavior
      switch effectiveBehavior {
      case .stop:
        removeCurrentAnimation()
        updateAnimationFrame(currentContext.playFrom)

      case .pause:
        removeCurrentAnimation()

      case .pauseAndRestore:
        currentContext.closure.ignoreDelegate = true
        removeCurrentAnimation()
        /// Keep the stale context around for when the app enters the foreground.
        animationContext = currentContext

      case .forceFinish:
        removeCurrentAnimation()
        updateAnimationFrame(currentContext.playTo)

      case .continuePlaying:
        break
      }
    }
  }

  public func updateAnimationForForegroundState(
    wasWaitingToPlayAnimation: Bool,
    backgroundBehavior: LottieBackgroundBehavior? = nil
  ) {
    if let currentContext = animationContext {
      let effectiveBehavior = backgroundBehavior ?? self.backgroundBehavior
      if wasWaitingToPlayAnimation {
        addNewAnimationForContext(currentContext)
      } else if effectiveBehavior == .pauseAndRestore {
        /// Restore animation from saved state
        updateInFlightAnimation()
      }
    }
  }

  // MARK: Internal