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

The issue of playing the same animated image link simultaneously on SDAnimatedImageView and UIImageView is as follows: #3667

Closed
pepsikirk opened this issue Jan 23, 2024 · 9 comments
Labels

Comments

@pepsikirk
Copy link

Issue Info

Info Value
Platform Name iOS
Platform Version 17.2.1
SDWebImage Version 5.18.10
Integration Method cocoapods
Xcode Version Xcode14.3.1
Repro rate 100%
Repro with our demo prj YES

Issue Description and Steps

For example, when a network animated image is downloaded and decoded into SDAnimatedImage for SDAnimatedImageView, it can play normally and is cached by SDMemoryCache. Subsequently, the same URL is downloaded into a UIImageView, and it retrieves the cached image from SDMemoryCache, which is an SDAnimatedImage. However, UIImageView is unable to display the SDAnimatedImage, resulting in the final display of a static image. How can this issue be resolved?

@dreampiggy
Copy link
Contributor

By designed issue.

The SDAnimatedImage and _UIAnimatedImage is not compatible.

If you use normal UIImageView to display GIF, which is indeed a bad idea. You can disable this by using the options override.

if context[.animatedImageClass] != SDAnimatedImgae.class {
    context.options |= .decodeFirstFrameOnly
}

@pepsikirk
Copy link
Author

By designed issue.

The SDAnimatedImage and _UIAnimatedImage is not compatible.

If you use normal UIImageView to display GIF, which is indeed a bad idea. You can disable this by using the options override.

if context[.animatedImageClass] != SDAnimatedImgae.class {
    context.options |= .decodeFirstFrameOnly
}

This is indeed not a good idea, but we do have such a business scenario, mainly occurring when displaying network avatars.
I noticed that the solution you provided is to use a static image display, while my expectation is to enable UIImageView to play the animated image dynamically, rather than just displaying the first frame.
Currently, does SDWebImage not support this scenario?

@dreampiggy
Copy link
Contributor

UIImageView is from Apple's UIKit, we can not change it's behavior or hook them

_UIAnimatedImage is the only API to make the UIImageView play animation. And, it's use CoreAnimation layer animation to replace each frame.

It can not supports to dynamic replacement himself.

Read more about why we introduce SDAnimatedImageView/SDAnimatedImage and subclass UIImageView/UIImage
https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#animated-image-50

@dreampiggy
Copy link
Contributor

dreampiggy commented Jan 24, 2024

I guess your question is:

Since SDAnimatedImage here contains a frame buffer pool, when I create another UIImage for the same image (means, the Data), can we steal the frame from it ?

Maybe, but this cause huge complicated.

If I really really has two image view, one is UIImageView, another is SDAnimatedImage, and want both of them showing the animation GIF, how can I do ?

Well, you can. Using the option SDWebImageMatchAnimatedImageClass. See why I introduce that option
#2801

Pay attention for RAM usage. UIAnimatedImage will always occupy bytesPerFrame * frame count, which means, a 1000*1000 100 frame GIF will occupy 381MB RAM

@dreampiggy
Copy link
Contributor

Oh, seems that SDWebImageMatchAnimatedImageClass does not solve this case. It will only ensure:

  1. Cached image is UIImage, but consumer is SDAnimatedImageView. Will assume cache miss and re-decoding

I guess your case seems to be:

  1. Cached image is SDAnimatedImage, but consumer is UIImageView

@pepsikirk
Copy link
Author

Oh, seems that SDWebImageMatchAnimatedImageClass does not solve this case. It will only ensure:

  1. Cached image is UIImage, but consumer is SDAnimatedImageView. Will assume cache miss and re-decoding

I guess your case seems to be:

  1. Cached image is SDAnimatedImage, but consumer is UIImageView

I understand, but the cost of replacing all UIImageViews that could potentially display animated images with SDAnimatedImageView in our application is somewhat high. Therefore, my current solution involves hooking the cacheKeyForURL:context: method and setting the key through SDWebImageContextAnimatedImageClass for identification. However, this approach is not quite elegant, and it also results in storing three identical copies of the data on the disk. So, I am still in the process of finding a better solution.

@dreampiggy
Copy link
Contributor

Need changes about how image stored and queried. A better design is to store both, with a modified key. Or using a more hackey way

A more hackey way can be like. UIImage instance use associated object to retain the SDAnimatedImage, or the reversed.

@dreampiggy
Copy link
Contributor

dreampiggy commented Jan 25, 2024

The original design of SDAnimatedImage because I don't think people still preferrs to use _UIAnimatedImage, which has high ratio from the design to cause OOM (which retain a NSArray<UIImage *> in memory, bad thing)

@pepsikirk
Copy link
Author

Thank you, I already know what to do.

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

No branches or pull requests

2 participants