Merge pull request #1575 from rs/gif

GIF support using FLAnimatedImage
This commit is contained in:
Bogdan Poplauschi 2016-06-07 12:57:51 +03:00
commit 4e2a4f091a
29 changed files with 588 additions and 552 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "Vendors/libwebp"]
path = Vendors/libwebp
url = https://github.com/webmproject/libwebp
[submodule "Vendors/FLAnimatedImage"]
path = Vendors/FLAnimatedImage
url = https://github.com/Flipboard/FLAnimatedImage

View File

@ -12,6 +12,4 @@
@property (strong, nonatomic) NSURL *imageURL;
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@end

View File

@ -8,9 +8,14 @@
#import "DetailViewController.h"
#import <SDWebImage/UIImageView+WebCache.h>
#import <SDWebImage/FLAnimatedImageView+WebCache.h>
@interface DetailViewController ()
@property (strong, nonatomic) IBOutlet FLAnimatedImageView *imageView;
- (void)configureView;
@end
@implementation DetailViewController

View File

@ -9,6 +9,36 @@
#import "MasterViewController.h"
#import <SDWebImage/UIImageView+WebCache.h>
#import "DetailViewController.h"
#import <SDWebImage/FLAnimatedImageView.h>
#import <SDWebImage/FLAnimatedImageView+WebCache.h>
@interface MyCustomTableViewCell : UITableViewCell
@property (nonatomic, strong) UILabel *customTextLabel;
@property (nonatomic, strong) FLAnimatedImageView *customImageView;
@end
@implementation MyCustomTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
_customImageView = [[FLAnimatedImageView alloc] initWithFrame:CGRectMake(20.0, 2.0, 60.0, 40.0)];
[self.contentView addSubview:_customImageView];
_customTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 12.0, 200, 20.0)];
[self.contentView addSubview:_customTextLabel];
_customImageView.clipsToBounds = YES;
_customImageView.contentMode = UIViewContentModeScaleAspectFill;
}
return self;
}
@end
@interface MasterViewController () {
NSMutableArray *_objects;
@ -38,6 +68,7 @@
_objects = [NSMutableArray arrayWithObjects:
@"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth
@"http://assets.sbnation.com/assets/2512203/dogflops.gif",
@"https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif",
@"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp",
@"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp",
nil];
@ -79,19 +110,23 @@
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
static UIImage *placeholderImage = nil;
if (!placeholderImage) {
placeholderImage = [UIImage imageNamed:@"placeholder"];
}
MyCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell.imageView setShowActivityIndicatorView:YES];
[cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];
cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
cell.imageView.contentMode = UIViewContentModeScaleAspectFill;
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:_objects[indexPath.row]]
placeholderImage:[UIImage imageNamed:@"placeholder"] options:indexPath.row == 0 ? SDWebImageRefreshCached : 0];
[cell.customImageView setShowActivityIndicatorView:YES];
[cell.customImageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];
cell.customTextLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
[cell.customImageView sd_setImageWithURL:[NSURL URLWithString:_objects[indexPath.row]]
placeholderImage:placeholderImage
options:indexPath.row == 0 ? SDWebImageRefreshCached : 0];
return cell;
}

View File

@ -1,164 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1296</int>
<string key="IBDocument.SystemVersion">11D50b</string>
<string key="IBDocument.InterfaceBuilderVersion">2182</string>
<string key="IBDocument.AppKitVersion">1138.32</string>
<string key="IBDocument.HIToolboxVersion">568.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">1181</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUIView</string>
<string>IBUIImageView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="975951072">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIView" id="191373211">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIImageView" id="268130440">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{320, 460}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<int key="IBUIContentMode">1</int>
<bool key="IBUIUserInteractionEnabled">NO</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace">
<int key="NSID">2</int>
</object>
</object>
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="191373211"/>
</object>
<int key="connectionID">3</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">imageView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="268130440"/>
</object>
<int key="connectionID">8</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="191373211"/>
<array class="NSMutableArray" key="children">
<reference ref="268130440"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="372490531"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="975951072"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="268130440"/>
<reference key="parent" ref="191373211"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">DetailViewController</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">8</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">DetailViewController</string>
<string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">imageView</string>
<string key="NS.object.0">UIImageView</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">imageView</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">imageView</string>
<string key="candidateClassName">UIImageView</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/DetailViewController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
<real value="1296" key="NS.object.0"/>
</object>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">1181</string>
</data>
</archive>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="DetailViewController">
<connections>
<outlet property="imageView" destination="7" id="8"/>
<outlet property="view" destination="1" id="3"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="1">
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" id="7" customClass="FLAnimatedImageView">
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</imageView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
</view>
</objects>
</document>

View File

@ -1,139 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1280</int>
<string key="IBDocument.SystemVersion">11C25</string>
<string key="IBDocument.InterfaceBuilderVersion">1919</string>
<string key="IBDocument.AppKitVersion">1138.11</string>
<string key="IBDocument.HIToolboxVersion">566.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">916</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUITableView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="841351856">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBProxyObject" id="371349661">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUITableView" id="709618507">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<string key="NSFrame">{{0, 20}, {320, 460}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
<bool key="IBUIClipsSubviews">YES</bool>
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBUIAlwaysBounceVertical">YES</bool>
<int key="IBUISeparatorStyle">1</int>
<int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
<bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
<float key="IBUIRowHeight">44</float>
<float key="IBUISectionHeaderHeight">22</float>
<float key="IBUISectionFooterHeight">22</float>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">view</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="709618507"/>
</object>
<int key="connectionID">3</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">dataSource</string>
<reference key="source" ref="709618507"/>
<reference key="destination" ref="841351856"/>
</object>
<int key="connectionID">4</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="709618507"/>
<reference key="destination" ref="841351856"/>
</object>
<int key="connectionID">5</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="841351856"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="371349661"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="709618507"/>
<reference key="parent" ref="0"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">MasterViewController</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">5</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">MasterViewController</string>
<string key="superclassName">UITableViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/MasterViewController.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">916</string>
</data>
</archive>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MasterViewController">
<connections>
<outlet property="view" destination="2" id="3"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="2">
<rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="dataSource" destination="-1" id="4"/>
<outlet property="delegate" destination="-1" id="5"/>
</connections>
</tableView>
</objects>
</document>

View File

@ -35,6 +35,16 @@ Pod::Spec.new do |s|
mk.dependency 'SDWebImage/Core'
end
s.subspec 'GIF' do |gif|
gif.ios.deployment_target = '6.0'
gif.source_files = 'SDWebImage/FLAnimatedImage/*.{h,m}'
gif.dependency 'SDWebImage/Core'
gif.dependency 'FLAnimatedImage', '~> 1.0'
gif.xcconfig = {
'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/FLAnimatedImage/FLAnimatedImage'
}
end
s.subspec 'WebP' do |webp|
webp.source_files = 'SDWebImage/UIImage+WebP.{h,m}'
webp.xcconfig = {

View File

@ -271,6 +271,24 @@
438096731CDFC08F00DC626B /* MKAnnotationView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 535699B515113E7300A4C397 /* MKAnnotationView+WebCache.m */; };
438096741CDFC09C00DC626B /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFB911762547C00698166 /* UIImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; };
438096751CDFC0A100DC626B /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; };
43CE75761CFE9427006C64D0 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE75771CFE9427006C64D0 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE75781CFE9427006C64D0 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE75791CFE9427006C64D0 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */; };
43CE757A1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */; };
43CE757B1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */; };
43CE757C1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE757D1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE757E1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE757F1CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */; };
43CE75801CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */; };
43CE75811CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */; };
43CE75D01CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE75D11CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE75D21CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
43CE75D31CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */; };
43CE75D41CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */; };
43CE75D51CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */; };
4A2CAE041AB4BB5400B6BC39 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
4A2CAE181AB4BB6400B6BC39 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D88148C56230056699D /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; };
4A2CAE191AB4BB6400B6BC39 /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 5340674F167780C40042B59E /* SDWebImageCompat.m */; };
@ -341,6 +359,12 @@
/* Begin PBXFileReference section */
00733A4C1BC487C000A5A117 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = "<group>"; };
43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImage.m; sourceTree = "<group>"; };
43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImageView.h; sourceTree = "<group>"; };
43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = "<group>"; };
43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImageView+WebCache.h"; sourceTree = "<group>"; };
43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImageView+WebCache.m"; sourceTree = "<group>"; };
4A2CADFF1AB4BB5300B6BC39 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4A2CAE021AB4BB5400B6BC39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImage.h; sourceTree = "<group>"; };
@ -487,6 +511,35 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
43CE75451CFE9427006C64D0 /* FLAnimatedImage */ = {
isa = PBXGroup;
children = (
43CE75481CFE9427006C64D0 /* FLAnimatedImage */,
);
name = FLAnimatedImage;
path = Vendors/FLAnimatedImage;
sourceTree = "<group>";
};
43CE75481CFE9427006C64D0 /* FLAnimatedImage */ = {
isa = PBXGroup;
children = (
43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */,
43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */,
43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */,
43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */,
);
path = FLAnimatedImage;
sourceTree = "<group>";
};
43CE75CD1CFE98B3006C64D0 /* FLAnimatedImage */ = {
isa = PBXGroup;
children = (
43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */,
43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */,
);
path = FLAnimatedImage;
sourceTree = "<group>";
};
4A2CAE001AB4BB5300B6BC39 /* WebImage */ = {
isa = PBXGroup;
children = (
@ -528,6 +581,7 @@
53922D71148C55820056699D /* Frameworks */ = {
isa = PBXGroup;
children = (
43CE75451CFE9427006C64D0 /* FLAnimatedImage */,
DA577C121998E60B007367ED /* libwebp */,
53FB893F14D35D1A0020B787 /* CoreGraphics.framework */,
53922D72148C55820056699D /* Foundation.framework */,
@ -546,6 +600,7 @@
53922DAA148C56470056699D /* Cache */,
53922DAC148C56DD0056699D /* Utils */,
53922DA9148C562D0056699D /* Categories */,
43CE75CD1CFE98B3006C64D0 /* FLAnimatedImage */,
);
path = SDWebImage;
sourceTree = "<group>";
@ -758,6 +813,7 @@
00733A6C1BC4880E00A5A117 /* UIButton+WebCache.h in Headers */,
431738DF1CDFC8A40008FEB9 /* vp8li.h in Headers */,
4317395B1CDFC8B70008FEB9 /* types.h in Headers */,
43CE75D21CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
431739551CDFC8B70008FEB9 /* decode.h in Headers */,
00733A731BC4880E00A5A117 /* SDWebImage.h in Headers */,
00733A701BC4880E00A5A117 /* UIImageView+HighlightedWebCache.h in Headers */,
@ -778,8 +834,10 @@
431738D41CDFC8A40008FEB9 /* alphai.h in Headers */,
431739581CDFC8B70008FEB9 /* format_constants.h in Headers */,
431739491CDFC8B20008FEB9 /* rescaler.h in Headers */,
43CE75781CFE9427006C64D0 /* FLAnimatedImage.h in Headers */,
431739161CDFC8AA0008FEB9 /* yuv.h in Headers */,
00733A6E1BC4880E00A5A117 /* UIImage+MultiFormat.h in Headers */,
43CE757E1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
431738DD1CDFC8A40008FEB9 /* vp8i.h in Headers */,
00733A6D1BC4880E00A5A117 /* UIImage+GIF.h in Headers */,
00733A651BC4880E00A5A117 /* SDWebImageDownloader.h in Headers */,
@ -796,6 +854,7 @@
files = (
4317394F1CDFC8B70008FEB9 /* demux.h in Headers */,
431739211CDFC8B20008FEB9 /* endian_inl.h in Headers */,
43CE757D1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
431739541CDFC8B70008FEB9 /* types.h in Headers */,
431738F51CDFC8AA0008FEB9 /* neon.h in Headers */,
431738C51CDFC8A30008FEB9 /* alphai.h in Headers */,
@ -809,6 +868,7 @@
4317392F1CDFC8B20008FEB9 /* rescaler.h in Headers */,
4A2CAE181AB4BB6400B6BC39 /* SDWebImageCompat.h in Headers */,
4317391B1CDFC8B20008FEB9 /* bit_reader.h in Headers */,
43CE75D11CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
4A2CAE331AB4BB7500B6BC39 /* UIImageView+HighlightedWebCache.h in Headers */,
431739521CDFC8B70008FEB9 /* mux.h in Headers */,
431738F11CDFC8AA0008FEB9 /* lossless.h in Headers */,
@ -821,6 +881,7 @@
431739291CDFC8B20008FEB9 /* quant_levels.h in Headers */,
4317391C1CDFC8B20008FEB9 /* bit_reader_inl.h in Headers */,
4317392B1CDFC8B20008FEB9 /* quant_levels_dec.h in Headers */,
43CE75771CFE9427006C64D0 /* FLAnimatedImage.h in Headers */,
4A2CAE2B1AB4BB7500B6BC39 /* UIButton+WebCache.h in Headers */,
4A2CAE251AB4BB7000B6BC39 /* SDWebImagePrefetcher.h in Headers */,
4A2CAE371AB4BB7500B6BC39 /* UIView+WebCacheOperation.h in Headers */,
@ -869,6 +930,7 @@
53761318155AD0D5005750A4 /* SDWebImageCompat.h in Headers */,
431738841CDFC2580008FEB9 /* vp8li.h in Headers */,
431738C31CDFC2660008FEB9 /* types.h in Headers */,
43CE75D01CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
431738BD1CDFC2660008FEB9 /* decode.h in Headers */,
53761319155AD0D5005750A4 /* SDWebImageDecoder.h in Headers */,
5376131A155AD0D5005750A4 /* SDWebImageDownloader.h in Headers */,
@ -889,8 +951,10 @@
431738791CDFC2580008FEB9 /* alphai.h in Headers */,
431738C01CDFC2660008FEB9 /* format_constants.h in Headers */,
431738B81CDFC2630008FEB9 /* rescaler.h in Headers */,
43CE75761CFE9427006C64D0 /* FLAnimatedImage.h in Headers */,
4317389F1CDFC25E0008FEB9 /* yuv.h in Headers */,
438096721CDFC08200DC626B /* MKAnnotationView+WebCache.h in Headers */,
43CE757C1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
431738821CDFC2580008FEB9 /* vp8i.h in Headers */,
AB615303192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */,
A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */,
@ -1038,6 +1102,7 @@
431739391CDFC8B20008FEB9 /* color_cache.c in Sources */,
00733A5A1BC4880000A5A117 /* SDWebImagePrefetcher.m in Sources */,
431739031CDFC8AA0008FEB9 /* dec_mips32.c in Sources */,
43CE75D51CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
4317390B1CDFC8AA0008FEB9 /* enc_sse2.c in Sources */,
00733A5B1BC4880000A5A117 /* NSData+ImageContentType.m in Sources */,
431739131CDFC8AA0008FEB9 /* upsampling_neon.c in Sources */,
@ -1074,6 +1139,7 @@
4317393C1CDFC8B20008FEB9 /* filters.c in Sources */,
431738DA1CDFC8A40008FEB9 /* quant.c in Sources */,
00733A591BC4880000A5A117 /* SDWebImageDecoder.m in Sources */,
43CE75811CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */,
00733A5F1BC4880000A5A117 /* UIImage+WebP.m in Sources */,
431739041CDFC8AA0008FEB9 /* dec_neon.c in Sources */,
431739441CDFC8B20008FEB9 /* quant_levels_dec.c in Sources */,
@ -1083,6 +1149,7 @@
431739141CDFC8AA0008FEB9 /* upsampling_sse2.c in Sources */,
00733A5D1BC4880000A5A117 /* UIImage+GIF.m in Sources */,
431738DC1CDFC8A40008FEB9 /* vp8.c in Sources */,
43CE757B1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
00733A571BC4880000A5A117 /* SDImageCache.m in Sources */,
4317394A1CDFC8B20008FEB9 /* thread.c in Sources */,
431739051CDFC8AA0008FEB9 /* dec_sse2.c in Sources */,
@ -1109,6 +1176,7 @@
4A2CAE2E1AB4BB7500B6BC39 /* UIImage+GIF.m in Sources */,
4A2CAE321AB4BB7500B6BC39 /* UIImage+WebP.m in Sources */,
431738EC1CDFC8AA0008FEB9 /* enc_avx2.c in Sources */,
43CE75D41CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
4317392E1CDFC8B20008FEB9 /* rescaler.c in Sources */,
431738E91CDFC8AA0008FEB9 /* dec_sse2.c in Sources */,
431738F71CDFC8AA0008FEB9 /* upsampling_neon.c in Sources */,
@ -1118,6 +1186,7 @@
431738F41CDFC8AA0008FEB9 /* lossless_sse2.c in Sources */,
431738EF1CDFC8AA0008FEB9 /* enc_sse2.c in Sources */,
431739301CDFC8B20008FEB9 /* thread.c in Sources */,
43CE757A1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
4A2CAE361AB4BB7500B6BC39 /* UIImageView+WebCache.m in Sources */,
431739221CDFC8B20008FEB9 /* filters.c in Sources */,
431738FB1CDFC8AA0008FEB9 /* yuv_mips32.c in Sources */,
@ -1155,6 +1224,7 @@
4A2CAE341AB4BB7500B6BC39 /* UIImageView+HighlightedWebCache.m in Sources */,
431738F81CDFC8AA0008FEB9 /* upsampling_sse2.c in Sources */,
4A2CAE201AB4BB6C00B6BC39 /* SDImageCache.m in Sources */,
43CE75801CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */,
431738C81CDFC8A30008FEB9 /* frame.c in Sources */,
4317391A1CDFC8B20008FEB9 /* bit_reader.c in Sources */,
431738E81CDFC8AA0008FEB9 /* dec_neon.c in Sources */,
@ -1177,6 +1247,7 @@
53761309155AD0D5005750A4 /* SDImageCache.m in Sources */,
5376130A155AD0D5005750A4 /* SDWebImageDecoder.m in Sources */,
431738911CDFC25E0008FEB9 /* enc_avx2.c in Sources */,
43CE75D31CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
431738B71CDFC2630008FEB9 /* rescaler.c in Sources */,
4317388E1CDFC25E0008FEB9 /* dec_sse2.c in Sources */,
4317389C1CDFC25E0008FEB9 /* upsampling_neon.c in Sources */,
@ -1186,6 +1257,7 @@
431738991CDFC25E0008FEB9 /* lossless_sse2.c in Sources */,
431738941CDFC25E0008FEB9 /* enc_sse2.c in Sources */,
431738B91CDFC2630008FEB9 /* thread.c in Sources */,
43CE75791CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
5376130B155AD0D5005750A4 /* SDWebImageDownloader.m in Sources */,
431738AB1CDFC2630008FEB9 /* filters.c in Sources */,
431738A01CDFC25E0008FEB9 /* yuv_mips32.c in Sources */,
@ -1223,6 +1295,7 @@
53EDFB8C17623F7C00698166 /* UIImage+MultiFormat.m in Sources */,
4317389D1CDFC25E0008FEB9 /* upsampling_sse2.c in Sources */,
ABBE71A818C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m in Sources */,
43CE757F1CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */,
4317387C1CDFC2580008FEB9 /* frame.c in Sources */,
431738A31CDFC2630008FEB9 /* bit_reader.c in Sources */,
4317388D1CDFC25E0008FEB9 /* dec_neon.c in Sources */,

View File

@ -0,0 +1,141 @@
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#if COCOAPODS
@import FLAnimatedImage;
#else
#import "FLAnimatedImageView.h"
#endif
#import "SDWebImageManager.h"
/**
* A category for the FLAnimatedImage imageView class that hooks it to the SDWebImage system.
* Very similar to the base class category (UIImageView (WebCache))
*/
@interface FLAnimatedImageView (WebCache)
/**
* Get the current image URL.
*
* Note that because of the limitations of categories this property can get out of sync
* if you use setImage: directly.
*/
- (nullable NSURL *)sd_imageURL;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
*
* @param url The url for the image.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
* Uses a placeholder until the request finishes.
*
* @param url The url for the image.
* @param placeholder The image to be set initially, until the image request finishes.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
* Uses a placeholder until the request finishes.
*
* @param url The url for the image.
* @param placeholder The image to be set initially, until the image request finishes.
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
*
* @param url The url for the image.
* @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network.
* The fourth parameter is the original image url.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
* Uses a placeholder until the request finishes.
*
* @param url The url for the image.
* @param placeholder The image to be set initially, until the image request finishes.
* @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network.
* The fourth parameter is the original image url.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
* Uses a placeholder until the request finishes.
*
* @param url The url for the image.
* @param placeholder The image to be set initially, until the image request finishes.
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
* @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network.
* The fourth parameter is the original image url.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
* The download is asynchronous and cached.
* Uses a placeholder until the request finishes.
*
* @param url The url for the image.
* @param placeholder The image to be set initially, until the image request finishes.
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
* @param progressBlock A block called while image is downloading
* @param completedBlock A block called when operation has been completed. This block has no return value
* and takes the requested UIImage as first parameter. In case of error the image parameter
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
* indicating if the image was retrieved from the local cache or from the network.
* The fourth parameter is the original image url.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Cancel the image load
*/
- (void)sd_cancelCurrentImageLoad;
@end

View File

@ -0,0 +1,119 @@
/*
* This file is part of the SDWebImage package.
* (c) Olivier Poitrey <rs@dailymotion.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
#import "FLAnimatedImageView+WebCache.h"
#import "objc/runtime.h"
#import "UIView+WebCacheOperation.h"
#import "NSData+ImageContentType.h"
#import "FLAnimatedImage.h"
#import "UIImageView+WebCache.h"
static char imageURLKey;
@implementation FLAnimatedImageView (WebCache)
- (nullable NSURL *)sd_imageURL {
return objc_getAssociatedObject(self, &imageURLKey);
}
- (void)sd_setImageWithURL:(nullable NSURL *)url {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_cancelCurrentImageLoad];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (!(options & SDWebImageDelayPlaceholder)) {
dispatch_main_async_safe(^{
self.image = placeholder;
});
}
if (url) {
// check if activityView is enabled or not
if ([self showActivityIndicatorView]) {
[self addActivityIndicator];
}
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return;
dispatch_main_sync_safe(^{
[wself removeActivityIndicator];
if (!wself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) {
completedBlock(image, error, cacheType, url);
return;
} else if (image) {
NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
if ([imageContentType isEqualToString:@"image/gif"]) {
wself.animatedImage = [FLAnimatedImage animatedImageWithGIFData:data];
wself.image = nil;
} else {
wself.image = image;
wself.animatedImage = nil;
}
[wself setNeedsLayout];
} else {
if ((options & SDWebImageDelayPlaceholder)) {
wself.image = placeholder;
[wself setNeedsLayout];
}
}
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
}];
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
} else {
dispatch_main_async_safe(^{
[self removeActivityIndicator];
if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
completedBlock(nil, error, SDImageCacheTypeNone, url);
}
});
}
}
- (void)sd_cancelCurrentImageLoad {
[self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"];
}
@end

View File

@ -18,7 +18,7 @@
* Get the current image URL.
*
* Note that because of the limitations of categories this property can get out of sync
* if you use sd_setImage: directly.
* if you use setImage: directly.
*/
- (nullable NSURL *)sd_imageURL;
@ -70,7 +70,7 @@
* The fourth parameter is the original image url.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder.
@ -87,7 +87,7 @@
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder and custom options.
@ -106,7 +106,7 @@
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Cancel the current download

View File

@ -30,18 +30,18 @@ static char imageURLKey;
[self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:nil options:0 completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock {
completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_cancelCurrentImageLoad];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
@ -49,7 +49,7 @@ static char imageURLKey;
if (url) {
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return;
dispatch_main_sync_safe(^{
__strong MKAnnotationView *sself = wself;

View File

@ -24,7 +24,7 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) {
SDImageCacheTypeMemory
};
typedef void(^SDWebImageQueryCompletedBlock)(UIImage * _Nullable image, SDImageCacheType cacheType);
typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);
typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache);
@ -148,7 +148,7 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
*
* @param key The unique key used to store the wanted image
*/
- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDWebImageQueryCompletedBlock)doneBlock;
- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock;
/**
* Query the memory cache synchronously.

View File

@ -10,6 +10,7 @@
#import "SDWebImageDecoder.h"
#import "UIImage+MultiFormat.h"
#import <CommonCrypto/CommonDigest.h>
#import "UIImage+GIF.h"
// See https://github.com/rs/SDWebImage/pull/1141 for discussion
@interface AutoPurgeCache : NSCache
@ -384,20 +385,24 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
return SDScaledImageForKey(key, image);
}
- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDWebImageQueryCompletedBlock)doneBlock {
- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock {
if (!doneBlock) {
return nil;
}
if (!key) {
doneBlock(nil, SDImageCacheTypeNone);
doneBlock(nil, nil, SDImageCacheTypeNone);
return nil;
}
// First check the in-memory cache...
UIImage *image = [self imageFromMemoryCacheForKey:key];
if (image) {
doneBlock(image, SDImageCacheTypeMemory);
NSData *diskData = nil;
if ([image isGIF]) {
diskData = [self diskImageDataBySearchingAllPathsForKey:key];
}
doneBlock(image, diskData, SDImageCacheTypeMemory);
return nil;
}
@ -408,6 +413,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
}
@autoreleasepool {
NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
UIImage *diskImage = [self diskImageForKey:key];
if (diskImage && self.shouldCacheImagesInMemory) {
NSUInteger cost = SDCacheCostForImage(diskImage);
@ -415,7 +421,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
}
dispatch_async(dispatch_get_main_queue(), ^{
doneBlock(diskImage, SDImageCacheTypeDisk);
doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
});
}
});

View File

@ -90,9 +90,9 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
SDWebImageAvoidAutoSetImage = 1 << 11
};
typedef void(^SDWebImageCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
typedef void(^SDWebImageCompletionWithFinishedBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL);
typedef void(^SDInternalCompletionBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL);
typedef NSString * _Nullable (^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable url);
@ -197,22 +197,24 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
*
* This parameter is required.
*
* This block has no return value and takes the requested UIImage as first parameter.
* In case of error the image parameter is nil and the second parameter may contain an NSError.
* This block has no return value and takes the requested UIImage as first parameter and the NSData representation as second parameter.
* In case of error the image parameter is nil and the third parameter may contain an NSError.
*
* The third parameter is an `SDImageCacheType` enum indicating if the image was retrieved from the local cache
* The forth parameter is an `SDImageCacheType` enum indicating if the image was retrieved from the local cache
* or from the memory cache or from the network.
*
* The last parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is
* The fith parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is
* downloading. This block is thus called repeatedly with a partial image. When image is fully downloaded, the
* block is called a last time with the full image and the last parameter set to YES.
*
* The last parameter is the original image URL
*
* @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation
*/
- (nullable id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionWithFinishedBlock)completedBlock;
completed:(nullable SDInternalCompletionBlock)completedBlock;
/**
* Saves image to cache for given URL

View File

@ -115,7 +115,7 @@
- (id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionWithFinishedBlock)completedBlock {
completed:(nullable SDInternalCompletionBlock)completedBlock {
// Invoking this method without a completedBlock is pointless
NSAssert(completedBlock != nil, @"If you mean to prefetch the image, use -[SDWebImagePrefetcher prefetchURLs] instead");
@ -143,7 +143,7 @@
if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
dispatch_main_sync_safe(^{
NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil];
completedBlock(nil, error, SDImageCacheTypeNone, YES, url);
completedBlock(nil, nil, error, SDImageCacheTypeNone, YES, url);
});
return operation;
}
@ -153,7 +153,7 @@
}
NSString *key = [self cacheKeyForURL:url];
operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType) {
operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *cachedImage, NSData *cachedData, SDImageCacheType cacheType) {
if (operation.isCancelled) {
@synchronized (self.runningOperations) {
[self.runningOperations removeObject:operation];
@ -162,12 +162,12 @@
return;
}
if ((!image || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) {
if (image && options & SDWebImageRefreshCached) {
if ((!cachedImage || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) {
if (cachedImage && options & SDWebImageRefreshCached) {
dispatch_main_sync_safe(^{
// If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image
// AND try to re-download it in order to let a chance to NSURLCache to refresh it from server.
completedBlock(image, nil, cacheType, YES, url);
completedBlock(cachedImage, cachedData, nil, cacheType, YES, url);
});
}
@ -180,23 +180,22 @@
if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies;
if (options & SDWebImageAllowInvalidSSLCertificates) downloaderOptions |= SDWebImageDownloaderAllowInvalidSSLCertificates;
if (options & SDWebImageHighPriority) downloaderOptions |= SDWebImageDownloaderHighPriority;
if (image && options & SDWebImageRefreshCached) {
if (cachedImage && options & SDWebImageRefreshCached) {
// force progressive off if image already cached but forced refreshing
downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload;
// ignore image read from NSURLCache if image if cached but force refreshing
downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
}
id subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) {
id subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *downloadedData, NSError *error, BOOL finished) {
__strong __typeof(weakOperation) strongOperation = weakOperation;
if (!strongOperation || strongOperation.isCancelled) {
// Do nothing if the operation was cancelled
// See #699 for more details
// if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data
}
else if (error) {
} else if (error) {
dispatch_main_sync_safe(^{
if (strongOperation && !strongOperation.isCancelled) {
completedBlock(nil, error, SDImageCacheTypeNone, finished, url);
completedBlock(nil, nil, error, SDImageCacheTypeNone, finished, url);
}
});
@ -221,33 +220,31 @@
BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly);
if (options & SDWebImageRefreshCached && image && !downloadedImage) {
if (options & SDWebImageRefreshCached && cachedImage && !downloadedImage) {
// Image refresh hit the NSURLCache cache, do not call the completion block
}
else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) {
} else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
if (transformedImage && finished) {
BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
[self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:(imageWasTransformed ? nil : data) forKey:key toDisk:cacheOnDisk];
[self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:(imageWasTransformed ? nil : downloadedData) forKey:key toDisk:cacheOnDisk];
}
dispatch_main_sync_safe(^{
if (strongOperation && !strongOperation.isCancelled) {
completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url);
completedBlock(transformedImage, downloadedData, nil, SDImageCacheTypeNone, finished, url);
}
});
});
}
else {
} else {
if (downloadedImage && finished) {
[self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk];
[self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:downloadedData forKey:key toDisk:cacheOnDisk];
}
dispatch_main_sync_safe(^{
if (strongOperation && !strongOperation.isCancelled) {
completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished, url);
completedBlock(downloadedImage, downloadedData, nil, SDImageCacheTypeNone, finished, url);
}
});
}
@ -271,24 +268,22 @@
}
}
};
}
else if (image) {
} else if (cachedImage) {
dispatch_main_sync_safe(^{
__strong __typeof(weakOperation) strongOperation = weakOperation;
if (strongOperation && !strongOperation.isCancelled) {
completedBlock(image, nil, cacheType, YES, url);
completedBlock(cachedImage, cachedData, nil, cacheType, YES, url);
}
});
@synchronized (self.runningOperations) {
[self.runningOperations removeObject:operation];
}
}
else {
} else {
// Image not in cache and download disallowed by delegate
dispatch_main_sync_safe(^{
__strong __typeof(weakOperation) strongOperation = weakOperation;
if (strongOperation && !weakOperation.isCancelled) {
completedBlock(nil, nil, SDImageCacheTypeNone, YES, url);
completedBlock(nil, nil, nil, SDImageCacheTypeNone, YES, url);
}
});
@synchronized (self.runningOperations) {

View File

@ -57,7 +57,7 @@
- (void)startPrefetchingAtIndex:(NSUInteger)index {
if (index >= self.prefetchURLs.count) return;
self.requestedCount++;
[self.manager loadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[self.manager loadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!finished) return;
self.finishedCount++;

View File

@ -81,7 +81,7 @@
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder.
@ -100,7 +100,7 @@
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder and custom options.
@ -121,7 +121,7 @@
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the backgroundImageView `image` with an `url`.
@ -178,7 +178,7 @@
*/
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the backgroundImageView `image` with an `url`, placeholder.
@ -197,7 +197,7 @@
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the backgroundImageView `image` with an `url`, placeholder and custom options.
@ -217,7 +217,7 @@
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Cancel the current image download

View File

@ -42,11 +42,11 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
[self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
}
@ -54,8 +54,7 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock {
completed:(nullable SDExternalCompletionBlock)completedBlock {
[self setImage:placeholder forState:state];
[self sd_cancelImageLoadForState:state];
@ -75,7 +74,7 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
self.imageURLStorage[@(state)] = url;
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return;
dispatch_main_sync_safe(^{
__strong UIButton *sself = wself;
@ -108,11 +107,11 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
}
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
}
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
}
@ -120,14 +119,14 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock {
completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_cancelBackgroundImageLoadForState:state];
[self setBackgroundImage:placeholder forState:state];
if (url) {
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return;
dispatch_main_sync_safe(^{
__strong UIButton *sself = wself;

View File

@ -11,10 +11,14 @@
@interface UIImage (GIF)
+ (UIImage *)sd_animatedGIFNamed:(NSString *)name;
/**
* Compatibility method - creates an animated UIImage from an NSData, it will only contain the 1st frame image
*/
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data;
- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size;
/**
* Checks if an UIImage instance is a GIF. Will use the `images` array
*/
- (BOOL)isGIF;
@end

View File

@ -9,6 +9,7 @@
#import "UIImage+GIF.h"
#import <ImageIO/ImageIO.h>
#import "objc/runtime.h"
@implementation UIImage (GIF)
@ -21,142 +22,26 @@
size_t count = CGImageSourceGetCount(source);
UIImage *animatedImage;
UIImage *staticImage;
if (count <= 1) {
animatedImage = [[UIImage alloc] initWithData:data];
}
else {
NSMutableArray *images = [NSMutableArray array];
NSTimeInterval duration = 0.0f;
for (size_t i = 0; i < count; i++) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (!image) {
continue;
}
duration += [self sd_frameDurationAtIndex:i source:source];
[images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
CGImageRelease(image);
}
if (!duration) {
duration = (1.0f / 10.0f) * count;
}
animatedImage = [UIImage animatedImageWithImages:images duration:duration];
staticImage = [[UIImage alloc] initWithData:data];
} else {
// we will only retrieve the 1st frame. the full GIF support is available via the FLAnimatedImageView category.
// this here is only code to allow drawing animated images as static ones
CGImageRef CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
UIImage *frameImage = [UIImage imageWithCGImage:CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
staticImage = [UIImage animatedImageWithImages:@[frameImage] duration:0.0f];
CGImageRelease(CGImage);
}
CFRelease(source);
return animatedImage;
return staticImage;
}
+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {
float frameDuration = 0.1f;
CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);
NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;
NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];
NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
if (delayTimeUnclampedProp) {
frameDuration = delayTimeUnclampedProp.floatValue;
}
else {
NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];
if (delayTimeProp) {
frameDuration = delayTimeProp.floatValue;
}
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
// We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
// a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
// for more information.
if (frameDuration < 0.011f) {
frameDuration = 0.100f;
}
CFRelease(cfFrameProperties);
return frameDuration;
}
+ (UIImage *)sd_animatedGIFNamed:(NSString *)name {
CGFloat scale = [UIScreen mainScreen].scale;
if (scale > 1.0f) {
NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"];
NSData *data = [NSData dataWithContentsOfFile:retinaPath];
if (data) {
return [UIImage sd_animatedGIFWithData:data];
}
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
data = [NSData dataWithContentsOfFile:path];
if (data) {
return [UIImage sd_animatedGIFWithData:data];
}
return [UIImage imageNamed:name];
}
else {
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];
NSData *data = [NSData dataWithContentsOfFile:path];
if (data) {
return [UIImage sd_animatedGIFWithData:data];
}
return [UIImage imageNamed:name];
}
}
- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size {
if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) {
return self;
}
CGSize scaledSize = size;
CGPoint thumbnailPoint = CGPointZero;
CGFloat widthFactor = size.width / self.size.width;
CGFloat heightFactor = size.height / self.size.height;
CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor;
scaledSize.width = self.size.width * scaleFactor;
scaledSize.height = self.size.height * scaleFactor;
if (widthFactor > heightFactor) {
thumbnailPoint.y = (size.height - scaledSize.height) * 0.5;
}
else if (widthFactor < heightFactor) {
thumbnailPoint.x = (size.width - scaledSize.width) * 0.5;
}
NSMutableArray *scaledImages = [NSMutableArray array];
for (UIImage *image in self.images) {
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
[image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
[scaledImages addObject:newImage];
UIGraphicsEndImageContext();
}
return [UIImage animatedImageWithImages:scaledImages duration:self.duration];
- (BOOL)isGIF {
return (self.images != nil);
}
@end

View File

@ -48,7 +48,7 @@
* The fourth parameter is the original image url.
*/
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `highlightedImage` with an `url` and custom options.
@ -65,7 +65,7 @@
*/
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `highlightedImage` with an `url` and custom options.
@ -84,7 +84,7 @@
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Cancel the current download

View File

@ -21,40 +21,39 @@
[self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil];
}
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock];
}
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url options:(SDWebImageOptions)options completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock];
}
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionBlock)completedBlock {
completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_cancelCurrentHighlightedImageLoad];
if (url) {
__weak __typeof(self)wself = self;
id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return;
dispatch_main_sync_safe (^
{
if (!wself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
wself.highlightedImage = image;
[wself setNeedsLayout];
}
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
dispatch_main_sync_safe (^{
if (!wself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
wself.highlightedImage = image;
[wself setNeedsLayout];
}
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
}];
[self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey];
} else {

View File

@ -48,7 +48,7 @@
* Get the current image URL.
*
* Note that because of the limitations of categories this property can get out of sync
* if you use sd_setImage: directly.
* if you use setImage: directly.
*/
- (nullable NSURL *)sd_imageURL;
@ -99,7 +99,7 @@
* The fourth parameter is the original image url.
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder.
@ -116,7 +116,7 @@
*/
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder and custom options.
@ -135,7 +135,7 @@
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url`, placeholder and custom options.
@ -156,7 +156,7 @@
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Set the imageView `image` with an `url` and optionally a placeholder image.
@ -177,7 +177,7 @@
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionBlock)completedBlock;
completed:(nullable SDExternalCompletionBlock)completedBlock;
/**
* Download an array of images and starts them in an animation loop
@ -205,4 +205,9 @@
*/
- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
- (BOOL)showActivityIndicatorView;
- (void)addActivityIndicator;
- (void)removeActivityIndicator;
@end

View File

@ -29,15 +29,15 @@ static char TAG_ACTIVITY_SHOW;
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
}
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDWebImageCompletionBlock)completedBlock {
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
}
@ -45,7 +45,7 @@ static char TAG_ACTIVITY_SHOW;
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionBlock)completedBlock {
completed:(nullable SDExternalCompletionBlock)completedBlock {
[self sd_cancelCurrentImageLoad];
objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
@ -63,7 +63,7 @@ static char TAG_ACTIVITY_SHOW;
}
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[wself removeActivityIndicator];
if (!wself) return;
dispatch_main_sync_safe(^{
@ -103,7 +103,7 @@ static char TAG_ACTIVITY_SHOW;
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageCompletionBlock)completedBlock {
completed:(nullable SDExternalCompletionBlock)completedBlock {
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
@ -121,7 +121,7 @@ static char TAG_ACTIVITY_SHOW;
NSMutableArray<id<SDWebImageOperation>> *operationsArray = [[NSMutableArray alloc] init];
for (NSURL *logoImageURL in arrayOfURLs) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (!wself) return;
dispatch_main_sync_safe(^{
__strong UIImageView *sself = wself;
@ -163,11 +163,11 @@ static char TAG_ACTIVITY_SHOW;
objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
}
- (void)setShowActivityIndicatorView:(BOOL)show{
- (void)setShowActivityIndicatorView:(BOOL)show {
objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, @(show), OBJC_ASSOCIATION_RETAIN);
}
- (BOOL)showActivityIndicatorView{
- (BOOL)showActivityIndicatorView {
return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue];
}

View File

@ -100,7 +100,7 @@ NSString *kImageTestKey = @"TestImageKey.jpg";
//- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
UIImage *imageForTesting = [self imageForTesting];
[self.sharedImageCache storeImage:imageForTesting forKey:kImageTestKey];
NSOperation *operation = [self.sharedImageCache queryDiskCacheForKey:kImageTestKey done:^(UIImage *image, SDImageCacheType cacheType) {
NSOperation *operation = [self.sharedImageCache queryDiskCacheForKey:kImageTestKey done:^(UIImage *image, NSData *data, SDImageCacheType cacheType) {
expect(image).to.equal(imageForTesting);
}];
expect(operation).toNot.beNil;

View File

@ -36,7 +36,7 @@
- (void)testThatDownloadingSameURLTwiceAndCancellingFirstWorks {
XCTestExpectation *expectation = [self expectationWithDescription:@"Correct image downloads"];
NSURL *imageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.jpg?20120509154705"];
NSURL *imageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage000.jpg"];
id token1 = [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL
options:0

View File

@ -40,7 +40,10 @@ static int64_t kAsyncTestTimeout = 5;
NSURL *originalImageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage000.jpg"];
[[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL
options:SDWebImageRefreshCached
progress:nil
completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
expect(image).toNot.beNil();
expect(error).to.beNil();
expect(originalImageURL).to.equal(imageURL);
@ -57,7 +60,10 @@ static int64_t kAsyncTestTimeout = 5;
NSURL *originalImageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.png"];
[[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL
options:SDWebImageRefreshCached
progress:nil
completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
expect(image).to.beNil();
expect(error).toNot.beNil();
expect(originalImageURL).to.equal(imageURL);

@ -0,0 +1 @@
Subproject commit 25307796cfcf66cb5b98774e050e93f64e0f2cde