SDWebImage / SDWebImageLinkPlugin

A SDWebImage loader plugin, to support load rich link image with LinkPresentation framework
MIT License
17 stars 2 forks source link

Possible to use both image urls and page urls (for link preview images) in one app for SDWebImage? #13

Closed inPhilly closed 4 years ago

inPhilly commented 4 years ago

This is my code to setup SDWebImageLinkPlugin in the application:didFinishLaunchingWithOptions: method of my application delegate:

[SDImageLoadersManager.sharedManager addLoader:SDImageLinkLoader.sharedLoader];
                    SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager;

Previously, I simply had: SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager;

Previously, I was always supplying an image URL as the url, and simply setting SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager; worked perfectly.

Now, adding [SDImageLoadersManager.sharedManager addLoader:SDImageLinkLoader.sharedLoader];

causes all of the calls to sd_setImageWithURL: in the app to assume that the url is page url as opposed to an image url.

I am primarily using page urls, but I just checked a viewController that had previously worked properly, and it is now assuming that the image urls I am providing for that controller are page urls.

So, what I am saying is that I have a combination of image urls and page urls (from which I want to display preview images) in my app. Am I forced to choose one of the other for the entire app? Or is there a way that I can specify per controller which type of url (image or page) I am supplying to the API? (PLEASE LET THIS BE THE CASE)

inPhilly commented 4 years ago

I figured out how to set per controller (or per call):

SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImageLinkLoader.sharedLoader];
SDImageLinkLoader.sharedLoader.shouldfetchVideoResources = NO;
[_linkView sd_setImageWithURL:[NSURL URLWithString:linkURLString] placeholderImage:nil options:0 context:@{SDWebImageContextCustomManager:manager}];
dreampiggy commented 4 years ago

@inPhilly This is a point. Because from our SDWebImage architecture for loader, it detect Which loader to use by only using the URL. See this API: canRequestImageForURL:

For the Link Presentation, it supports any of URL (site, or downloadable content), such like www.apple.com.

For the normal image downloading, it supports only the downlodable content. But the fact is that the image URL does not always end with some format extension. For example, https://www.gravatar.com/avatar/4a042b8382a008d344561c8301509f3a?s=32&d=identicon&r=PG does not end with a *.png.

For this case, the SDWebImageDownloader and SDImageLinkLoader currently can not detect which URL is a image data URL, which is a Link Presentation URL. So, if you just add the loader, the last added one will have the high priority and request that instead.

I don't find anything good solution for this case. One possible solution is to filter, if URL is end with a file extention (like www.apple.com/a.png, www.apple.com/a.json), then the - [SDImageLinkLoader canRequestImageForURL:] return NO and fallback to normal image data loading. But this may still miss the case when image data URL does not have extension (like https://www.gravatar.com/avatar/4a042b8382a008d344561c8301509f3a?s=32&d=identicon&r=PG)

If you want the simple filter above, I can add this. But pay attention to the case I talked above.

inPhilly commented 4 years ago

This solution works for me:

For Image URL:

SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDWebImageDownloader.sharedDownloader];
[_linkView sd_setImageWithURL:imageURL placeholderImage:nil options:0 context:@{SDWebImageContextCustomManager:manager}];

For Page URL:

SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImageLinkLoader.sharedLoader];
SDImageLinkLoader.sharedLoader.shouldfetchVideoResources = NO;
[_linkView sd_setImageWithURL:pageURL placeholderImage:nil options:0 context:@{SDWebImageContextCustomManager:manager}];

I just need to set a custom manager for every call to sd_setImageWithURL:. Also, I do not include the following code at all in the app:

[SDImageLoadersManager.sharedManager addLoader:SDImageLinkLoader.sharedLoader];
SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager;

Does this seem right to you?

inPhilly commented 4 years ago

I do know which of my URLs are image URLs and which are page URLs.

dreampiggy commented 4 years ago

I do know which of my URLs are image URLs and which are page URLs.

Our framework don’t know as well.

inPhilly commented 4 years ago

I'm saying that I do know. Given that I do know, will my solution work?

dreampiggy commented 4 years ago

@inPhilly Sorry, my typo. If you know that all your URL is site URL (but not image data URL), you can use the code to pass a custom manager with SDImageLinkLoader associated. This code is correct.

inPhilly commented 4 years ago

I'm saying that on certain controllers, URLs are site URLs, and on other controllers, URLs are image URLs. So on a controller that has site URLs, I use this code:

SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImageLinkLoader.sharedLoader];
SDImageLinkLoader.sharedLoader.shouldfetchVideoResources = NO;
[_linkView sd_setImageWithURL:pageURL placeholderImage:nil options:0 context:@{SDWebImageContextCustomManager:manager}];

And on a controller that has image URLs, I use this code:

SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDWebImageDownloader.sharedDownloader];
[_linkView sd_setImageWithURL:imageURL placeholderImage:nil options:0 context:@{SDWebImageContextCustomManager:manager}];

This is correct, right?

dreampiggy commented 4 years ago

And on a controller that has image URLs,

For this case, since the SDWebImageDownloader is the default loader, you don't need a custom manager. Use the SDWebImage sd_setImage API withuot any options or context is OK.

If you're confused about this, check the Wiki here and Docuementation again.