Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add on onAnimationReady function support for delayed animation loading #1802

Closed
wants to merge 11 commits into from
Closed

Conversation

rasberik
Copy link

@rasberik rasberik commented Nov 10, 2022

Problem scope

Currently there is issue play() method getting called after LottieAnimationView has been initialized, but animation is not loaded yet for newly added .lottie format, which needs file processing before animation is ready.

// AnimationViewInitializers
DotLottieFile.named(name, bundle: bundle, dotLottieCache: dotLottieCache) { result in
      guard case Result.success(let lottie) = result else { return }
      self.loadAnimation(animationId, from: lottie)
    }

there is currently no way to know when it is completed or way to properly handle it.
I propose solution that doesn't require complete rewrite of view lifecycle after changing to .lottie format.

// LottieAnimationView
public func play(completion: LottieCompletionBlock? = nil) {
    guard let animation = animation else {
      // current behavior for play when using `.lottie` files is returned due to missing animation
      // behavior might success depend on file size that needs to be processed, not tested
      return
    }
    ...
  }

How to Reproduce

Simply create LottieAnimationView using any local .dotlottie resource based initializer, bigger file size will guarantee the reproduction (30kb+). Key is to call play fast enough after calling the initializer

let lottieAnimationView = LottieAnimationView(dotLottieName: resourceName, bundle: bundle)
// ... layout ...
lottieAnimationView.play()

You can refer to added tests that can confirm the problem.

Proposed Solution

Until more proper alternative is found, I would like to suggest using functional method onAnimationReady that will return a closure with self (LottieAnimationView).
This helps to keep code changes to minimum, and works similarly to all local and remote types.
It does not alter existing behavior, and works as convenient method for those who might need it.

Usage

Before:

func play(completion: CompletionHandler? {
   view.play(completion: completion)
}

After:

func play(completion: CompletionHandler?) {
   lotView.onAnimationReady { view in
      view.play(completion: completion) // any type of `play(...)` or other methods on view can be called without self capture in most use cases
   }
}

@rasberik
Copy link
Author

rasberik commented Nov 10, 2022

@calda Added tests that confirm both problem and workaround behavior.

// MARK: Internal

func test_dotLottieFile_hasAnimation_onInitialize() {
XCTExpectFailure("This is expected failure due to loading delay")
Copy link
Author

@rasberik rasberik Nov 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note] This is the proof of the underlying issue.

Different from test_jsonFile_hasAnimation_onInitialize, which is succeeding.

@calda
Copy link
Member

calda commented Nov 11, 2022

Thanks for the report -- I made changes in #1810 that I think resolve this issue, with a slightly different approach.

@calda calda closed this Nov 11, 2022
@calda
Copy link
Member

calda commented Nov 11, 2022

e.g. you will be able to do:

let animationView = LottieAnimationView(
  dotLottieName: "DotLottie/animation",
  completion: { animationView in
    animationView.play()
  })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants