Authored by Bogdan Poplauschi

Merge pull request #1575 from rs/gif

GIF support using FLAnimatedImage
1 [submodule "Vendors/libwebp"] 1 [submodule "Vendors/libwebp"]
2 path = Vendors/libwebp 2 path = Vendors/libwebp
3 url = https://github.com/webmproject/libwebp 3 url = https://github.com/webmproject/libwebp
  4 +[submodule "Vendors/FLAnimatedImage"]
  5 + path = Vendors/FLAnimatedImage
  6 + url = https://github.com/Flipboard/FLAnimatedImage
@@ -12,6 +12,4 @@ @@ -12,6 +12,4 @@
12 12
13 @property (strong, nonatomic) NSURL *imageURL; 13 @property (strong, nonatomic) NSURL *imageURL;
14 14
15 -@property (strong, nonatomic) IBOutlet UIImageView *imageView;  
16 -  
17 @end 15 @end
@@ -8,9 +8,14 @@ @@ -8,9 +8,14 @@
8 8
9 #import "DetailViewController.h" 9 #import "DetailViewController.h"
10 #import <SDWebImage/UIImageView+WebCache.h> 10 #import <SDWebImage/UIImageView+WebCache.h>
  11 +#import <SDWebImage/FLAnimatedImageView+WebCache.h>
11 12
12 @interface DetailViewController () 13 @interface DetailViewController ()
  14 +
  15 +@property (strong, nonatomic) IBOutlet FLAnimatedImageView *imageView;
  16 +
13 - (void)configureView; 17 - (void)configureView;
  18 +
14 @end 19 @end
15 20
16 @implementation DetailViewController 21 @implementation DetailViewController
@@ -9,6 +9,36 @@ @@ -9,6 +9,36 @@
9 #import "MasterViewController.h" 9 #import "MasterViewController.h"
10 #import <SDWebImage/UIImageView+WebCache.h> 10 #import <SDWebImage/UIImageView+WebCache.h>
11 #import "DetailViewController.h" 11 #import "DetailViewController.h"
  12 +#import <SDWebImage/FLAnimatedImageView.h>
  13 +#import <SDWebImage/FLAnimatedImageView+WebCache.h>
  14 +
  15 +
  16 +@interface MyCustomTableViewCell : UITableViewCell
  17 +
  18 +@property (nonatomic, strong) UILabel *customTextLabel;
  19 +@property (nonatomic, strong) FLAnimatedImageView *customImageView;
  20 +
  21 +@end
  22 +
  23 +
  24 +@implementation MyCustomTableViewCell
  25 +
  26 +- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
  27 + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
  28 + _customImageView = [[FLAnimatedImageView alloc] initWithFrame:CGRectMake(20.0, 2.0, 60.0, 40.0)];
  29 + [self.contentView addSubview:_customImageView];
  30 + _customTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 12.0, 200, 20.0)];
  31 + [self.contentView addSubview:_customTextLabel];
  32 +
  33 + _customImageView.clipsToBounds = YES;
  34 + _customImageView.contentMode = UIViewContentModeScaleAspectFill;
  35 + }
  36 + return self;
  37 +}
  38 +
  39 +@end
  40 +
  41 +
12 42
13 @interface MasterViewController () { 43 @interface MasterViewController () {
14 NSMutableArray *_objects; 44 NSMutableArray *_objects;
@@ -38,6 +68,7 @@ @@ -38,6 +68,7 @@
38 _objects = [NSMutableArray arrayWithObjects: 68 _objects = [NSMutableArray arrayWithObjects:
39 @"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth 69 @"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth
40 @"http://assets.sbnation.com/assets/2512203/dogflops.gif", 70 @"http://assets.sbnation.com/assets/2512203/dogflops.gif",
  71 + @"https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif",
41 @"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp", 72 @"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp",
42 @"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp", 73 @"http://www.ioncannon.net/wp-content/uploads/2011/06/test9.webp",
43 nil]; 74 nil];
@@ -79,19 +110,23 @@ @@ -79,19 +110,23 @@
79 { 110 {
80 static NSString *CellIdentifier = @"Cell"; 111 static NSString *CellIdentifier = @"Cell";
81 112
82 - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];  
83 - if (cell == nil)  
84 - {  
85 - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 113 + static UIImage *placeholderImage = nil;
  114 + if (!placeholderImage) {
  115 + placeholderImage = [UIImage imageNamed:@"placeholder"];
  116 + }
  117 +
  118 + MyCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  119 + if (cell == nil) {
  120 + cell = [[MyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
86 } 121 }
87 122
88 - [cell.imageView setShowActivityIndicatorView:YES];  
89 - [cell.imageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];  
90 -  
91 - cell.textLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];  
92 - cell.imageView.contentMode = UIViewContentModeScaleAspectFill;  
93 - [cell.imageView sd_setImageWithURL:[NSURL URLWithString:_objects[indexPath.row]]  
94 - placeholderImage:[UIImage imageNamed:@"placeholder"] options:indexPath.row == 0 ? SDWebImageRefreshCached : 0]; 123 + [cell.customImageView setShowActivityIndicatorView:YES];
  124 + [cell.customImageView setIndicatorStyle:UIActivityIndicatorViewStyleGray];
  125 +
  126 + cell.customTextLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row];
  127 + [cell.customImageView sd_setImageWithURL:[NSURL URLWithString:_objects[indexPath.row]]
  128 + placeholderImage:placeholderImage
  129 + options:indexPath.row == 0 ? SDWebImageRefreshCached : 0];
95 return cell; 130 return cell;
96 } 131 }
97 132
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">  
3 - <data>  
4 - <int key="IBDocument.SystemTarget">1296</int>  
5 - <string key="IBDocument.SystemVersion">11D50b</string>  
6 - <string key="IBDocument.InterfaceBuilderVersion">2182</string>  
7 - <string key="IBDocument.AppKitVersion">1138.32</string>  
8 - <string key="IBDocument.HIToolboxVersion">568.00</string>  
9 - <object class="NSMutableDictionary" key="IBDocument.PluginVersions">  
10 - <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
11 - <string key="NS.object.0">1181</string>  
12 - </object>  
13 - <array key="IBDocument.IntegratedClassDependencies">  
14 - <string>IBProxyObject</string>  
15 - <string>IBUIView</string>  
16 - <string>IBUIImageView</string>  
17 - </array>  
18 - <array key="IBDocument.PluginDependencies">  
19 - <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
20 - </array>  
21 - <object class="NSMutableDictionary" key="IBDocument.Metadata">  
22 - <string key="NS.key.0">PluginDependencyRecalculationVersion</string>  
23 - <integer value="1" key="NS.object.0"/>  
24 - </object>  
25 - <array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">  
26 - <object class="IBProxyObject" id="372490531">  
27 - <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>  
28 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
29 - </object>  
30 - <object class="IBProxyObject" id="975951072">  
31 - <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>  
32 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
33 - </object>  
34 - <object class="IBUIView" id="191373211">  
35 - <reference key="NSNextResponder"/>  
36 - <int key="NSvFlags">274</int>  
37 - <array class="NSMutableArray" key="NSSubviews">  
38 - <object class="IBUIImageView" id="268130440">  
39 - <reference key="NSNextResponder" ref="191373211"/>  
40 - <int key="NSvFlags">274</int>  
41 - <string key="NSFrameSize">{320, 460}</string>  
42 - <reference key="NSSuperview" ref="191373211"/>  
43 - <reference key="NSWindow"/>  
44 - <string key="NSReuseIdentifierKey">_NS:9</string>  
45 - <int key="IBUIContentMode">1</int>  
46 - <bool key="IBUIUserInteractionEnabled">NO</bool>  
47 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
48 - </object>  
49 - </array>  
50 - <string key="NSFrame">{{0, 20}, {320, 460}}</string>  
51 - <reference key="NSSuperview"/>  
52 - <reference key="NSWindow"/>  
53 - <object class="NSColor" key="IBUIBackgroundColor">  
54 - <int key="NSColorSpace">3</int>  
55 - <bytes key="NSWhite">MQA</bytes>  
56 - <object class="NSColorSpace" key="NSCustomColorSpace">  
57 - <int key="NSID">2</int>  
58 - </object>  
59 - </object>  
60 - <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>  
61 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
62 - </object>  
63 - </array>  
64 - <object class="IBObjectContainer" key="IBDocument.Objects">  
65 - <array class="NSMutableArray" key="connectionRecords">  
66 - <object class="IBConnectionRecord">  
67 - <object class="IBCocoaTouchOutletConnection" key="connection">  
68 - <string key="label">view</string>  
69 - <reference key="source" ref="372490531"/>  
70 - <reference key="destination" ref="191373211"/>  
71 - </object>  
72 - <int key="connectionID">3</int>  
73 - </object>  
74 - <object class="IBConnectionRecord">  
75 - <object class="IBCocoaTouchOutletConnection" key="connection">  
76 - <string key="label">imageView</string>  
77 - <reference key="source" ref="372490531"/>  
78 - <reference key="destination" ref="268130440"/>  
79 - </object>  
80 - <int key="connectionID">8</int>  
81 - </object>  
82 - </array>  
83 - <object class="IBMutableOrderedSet" key="objectRecords">  
84 - <array key="orderedObjects">  
85 - <object class="IBObjectRecord">  
86 - <int key="objectID">0</int>  
87 - <array key="object" id="0"/>  
88 - <reference key="children" ref="1000"/>  
89 - <nil key="parent"/>  
90 - </object>  
91 - <object class="IBObjectRecord">  
92 - <int key="objectID">1</int>  
93 - <reference key="object" ref="191373211"/>  
94 - <array class="NSMutableArray" key="children">  
95 - <reference ref="268130440"/>  
96 - </array>  
97 - <reference key="parent" ref="0"/>  
98 - </object>  
99 - <object class="IBObjectRecord">  
100 - <int key="objectID">-1</int>  
101 - <reference key="object" ref="372490531"/>  
102 - <reference key="parent" ref="0"/>  
103 - <string key="objectName">File's Owner</string>  
104 - </object>  
105 - <object class="IBObjectRecord">  
106 - <int key="objectID">-2</int>  
107 - <reference key="object" ref="975951072"/>  
108 - <reference key="parent" ref="0"/>  
109 - </object>  
110 - <object class="IBObjectRecord">  
111 - <int key="objectID">7</int>  
112 - <reference key="object" ref="268130440"/>  
113 - <reference key="parent" ref="191373211"/>  
114 - </object>  
115 - </array>  
116 - </object>  
117 - <dictionary class="NSMutableDictionary" key="flattenedProperties">  
118 - <string key="-1.CustomClassName">DetailViewController</string>  
119 - <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
120 - <string key="-2.CustomClassName">UIResponder</string>  
121 - <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
122 - <string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
123 - <string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
124 - </dictionary>  
125 - <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>  
126 - <nil key="activeLocalization"/>  
127 - <dictionary class="NSMutableDictionary" key="localizations"/>  
128 - <nil key="sourceID"/>  
129 - <int key="maxID">8</int>  
130 - </object>  
131 - <object class="IBClassDescriber" key="IBDocument.Classes">  
132 - <array class="NSMutableArray" key="referencedPartialClassDescriptions">  
133 - <object class="IBPartialClassDescription">  
134 - <string key="className">DetailViewController</string>  
135 - <string key="superclassName">UIViewController</string>  
136 - <object class="NSMutableDictionary" key="outlets">  
137 - <string key="NS.key.0">imageView</string>  
138 - <string key="NS.object.0">UIImageView</string>  
139 - </object>  
140 - <object class="NSMutableDictionary" key="toOneOutletInfosByName">  
141 - <string key="NS.key.0">imageView</string>  
142 - <object class="IBToOneOutletInfo" key="NS.object.0">  
143 - <string key="name">imageView</string>  
144 - <string key="candidateClassName">UIImageView</string>  
145 - </object>  
146 - </object>  
147 - <object class="IBClassDescriptionSource" key="sourceIdentifier">  
148 - <string key="majorKey">IBProjectSource</string>  
149 - <string key="minorKey">./Classes/DetailViewController.h</string>  
150 - </object>  
151 - </object>  
152 - </array>  
153 - </object>  
154 - <int key="IBDocument.localizationMode">0</int>  
155 - <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>  
156 - <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">  
157 - <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>  
158 - <real value="1296" key="NS.object.0"/>  
159 - </object>  
160 - <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>  
161 - <int key="IBDocument.defaultPropertyAccessControl">3</int>  
162 - <string key="IBCocoaTouchPluginVersion">1181</string>  
163 - </data>  
164 -</archive> 1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
  3 + <dependencies>
  4 + <deployment identifier="iOS"/>
  5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
  6 + </dependencies>
  7 + <objects>
  8 + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="DetailViewController">
  9 + <connections>
  10 + <outlet property="imageView" destination="7" id="8"/>
  11 + <outlet property="view" destination="1" id="3"/>
  12 + </connections>
  13 + </placeholder>
  14 + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
  15 + <view contentMode="scaleToFill" id="1">
  16 + <rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
  17 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  18 + <subviews>
  19 + <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" id="7" customClass="FLAnimatedImageView">
  20 + <rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
  21 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  22 + </imageView>
  23 + </subviews>
  24 + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
  25 + <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
  26 + </view>
  27 + </objects>
  28 +</document>
1 -<?xml version="1.0" encoding="UTF-8"?>  
2 -<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">  
3 - <data>  
4 - <int key="IBDocument.SystemTarget">1280</int>  
5 - <string key="IBDocument.SystemVersion">11C25</string>  
6 - <string key="IBDocument.InterfaceBuilderVersion">1919</string>  
7 - <string key="IBDocument.AppKitVersion">1138.11</string>  
8 - <string key="IBDocument.HIToolboxVersion">566.00</string>  
9 - <object class="NSMutableDictionary" key="IBDocument.PluginVersions">  
10 - <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
11 - <string key="NS.object.0">916</string>  
12 - </object>  
13 - <array key="IBDocument.IntegratedClassDependencies">  
14 - <string>IBProxyObject</string>  
15 - <string>IBUITableView</string>  
16 - </array>  
17 - <array key="IBDocument.PluginDependencies">  
18 - <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
19 - </array>  
20 - <object class="NSMutableDictionary" key="IBDocument.Metadata">  
21 - <string key="NS.key.0">PluginDependencyRecalculationVersion</string>  
22 - <integer value="1" key="NS.object.0"/>  
23 - </object>  
24 - <array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">  
25 - <object class="IBProxyObject" id="841351856">  
26 - <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>  
27 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
28 - </object>  
29 - <object class="IBProxyObject" id="371349661">  
30 - <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>  
31 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
32 - </object>  
33 - <object class="IBUITableView" id="709618507">  
34 - <reference key="NSNextResponder"/>  
35 - <int key="NSvFlags">274</int>  
36 - <string key="NSFrame">{{0, 20}, {320, 460}}</string>  
37 - <reference key="NSSuperview"/>  
38 - <reference key="NSWindow"/>  
39 - <object class="NSColor" key="IBUIBackgroundColor">  
40 - <int key="NSColorSpace">3</int>  
41 - <bytes key="NSWhite">MQA</bytes>  
42 - </object>  
43 - <bool key="IBUIClipsSubviews">YES</bool>  
44 - <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>  
45 - <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>  
46 - <bool key="IBUIAlwaysBounceVertical">YES</bool>  
47 - <int key="IBUISeparatorStyle">1</int>  
48 - <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>  
49 - <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>  
50 - <float key="IBUIRowHeight">44</float>  
51 - <float key="IBUISectionHeaderHeight">22</float>  
52 - <float key="IBUISectionFooterHeight">22</float>  
53 - </object>  
54 - </array>  
55 - <object class="IBObjectContainer" key="IBDocument.Objects">  
56 - <array class="NSMutableArray" key="connectionRecords">  
57 - <object class="IBConnectionRecord">  
58 - <object class="IBCocoaTouchOutletConnection" key="connection">  
59 - <string key="label">view</string>  
60 - <reference key="source" ref="841351856"/>  
61 - <reference key="destination" ref="709618507"/>  
62 - </object>  
63 - <int key="connectionID">3</int>  
64 - </object>  
65 - <object class="IBConnectionRecord">  
66 - <object class="IBCocoaTouchOutletConnection" key="connection">  
67 - <string key="label">dataSource</string>  
68 - <reference key="source" ref="709618507"/>  
69 - <reference key="destination" ref="841351856"/>  
70 - </object>  
71 - <int key="connectionID">4</int>  
72 - </object>  
73 - <object class="IBConnectionRecord">  
74 - <object class="IBCocoaTouchOutletConnection" key="connection">  
75 - <string key="label">delegate</string>  
76 - <reference key="source" ref="709618507"/>  
77 - <reference key="destination" ref="841351856"/>  
78 - </object>  
79 - <int key="connectionID">5</int>  
80 - </object>  
81 - </array>  
82 - <object class="IBMutableOrderedSet" key="objectRecords">  
83 - <array key="orderedObjects">  
84 - <object class="IBObjectRecord">  
85 - <int key="objectID">0</int>  
86 - <array key="object" id="0"/>  
87 - <reference key="children" ref="1000"/>  
88 - <nil key="parent"/>  
89 - </object>  
90 - <object class="IBObjectRecord">  
91 - <int key="objectID">-1</int>  
92 - <reference key="object" ref="841351856"/>  
93 - <reference key="parent" ref="0"/>  
94 - <string key="objectName">File's Owner</string>  
95 - </object>  
96 - <object class="IBObjectRecord">  
97 - <int key="objectID">-2</int>  
98 - <reference key="object" ref="371349661"/>  
99 - <reference key="parent" ref="0"/>  
100 - </object>  
101 - <object class="IBObjectRecord">  
102 - <int key="objectID">2</int>  
103 - <reference key="object" ref="709618507"/>  
104 - <reference key="parent" ref="0"/>  
105 - </object>  
106 - </array>  
107 - </object>  
108 - <dictionary class="NSMutableDictionary" key="flattenedProperties">  
109 - <string key="-1.CustomClassName">MasterViewController</string>  
110 - <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
111 - <string key="-2.CustomClassName">UIResponder</string>  
112 - <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
113 - <string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>  
114 - </dictionary>  
115 - <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>  
116 - <nil key="activeLocalization"/>  
117 - <dictionary class="NSMutableDictionary" key="localizations"/>  
118 - <nil key="sourceID"/>  
119 - <int key="maxID">5</int>  
120 - </object>  
121 - <object class="IBClassDescriber" key="IBDocument.Classes">  
122 - <array class="NSMutableArray" key="referencedPartialClassDescriptions">  
123 - <object class="IBPartialClassDescription">  
124 - <string key="className">MasterViewController</string>  
125 - <string key="superclassName">UITableViewController</string>  
126 - <object class="IBClassDescriptionSource" key="sourceIdentifier">  
127 - <string key="majorKey">IBProjectSource</string>  
128 - <string key="minorKey">./Classes/MasterViewController.h</string>  
129 - </object>  
130 - </object>  
131 - </array>  
132 - </object>  
133 - <int key="IBDocument.localizationMode">0</int>  
134 - <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>  
135 - <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>  
136 - <int key="IBDocument.defaultPropertyAccessControl">3</int>  
137 - <string key="IBCocoaTouchPluginVersion">916</string>  
138 - </data>  
139 -</archive> 1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
  3 + <dependencies>
  4 + <deployment identifier="iOS"/>
  5 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
  6 + </dependencies>
  7 + <objects>
  8 + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MasterViewController">
  9 + <connections>
  10 + <outlet property="view" destination="2" id="3"/>
  11 + </connections>
  12 + </placeholder>
  13 + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
  14 + <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" id="2">
  15 + <rect key="frame" x="0.0" y="0.0" width="320" height="460"/>
  16 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  17 + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
  18 + <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
  19 + <connections>
  20 + <outlet property="dataSource" destination="-1" id="4"/>
  21 + <outlet property="delegate" destination="-1" id="5"/>
  22 + </connections>
  23 + </tableView>
  24 + </objects>
  25 +</document>
@@ -35,6 +35,16 @@ Pod::Spec.new do |s| @@ -35,6 +35,16 @@ Pod::Spec.new do |s|
35 mk.dependency 'SDWebImage/Core' 35 mk.dependency 'SDWebImage/Core'
36 end 36 end
37 37
  38 + s.subspec 'GIF' do |gif|
  39 + gif.ios.deployment_target = '6.0'
  40 + gif.source_files = 'SDWebImage/FLAnimatedImage/*.{h,m}'
  41 + gif.dependency 'SDWebImage/Core'
  42 + gif.dependency 'FLAnimatedImage', '~> 1.0'
  43 + gif.xcconfig = {
  44 + 'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/FLAnimatedImage/FLAnimatedImage'
  45 + }
  46 + end
  47 +
38 s.subspec 'WebP' do |webp| 48 s.subspec 'WebP' do |webp|
39 webp.source_files = 'SDWebImage/UIImage+WebP.{h,m}' 49 webp.source_files = 'SDWebImage/UIImage+WebP.{h,m}'
40 webp.xcconfig = { 50 webp.xcconfig = {
@@ -271,6 +271,24 @@ @@ -271,6 +271,24 @@
271 438096731CDFC08F00DC626B /* MKAnnotationView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 535699B515113E7300A4C397 /* MKAnnotationView+WebCache.m */; }; 271 438096731CDFC08F00DC626B /* MKAnnotationView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 535699B515113E7300A4C397 /* MKAnnotationView+WebCache.m */; };
272 438096741CDFC09C00DC626B /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFB911762547C00698166 /* UIImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; }; 272 438096741CDFC09C00DC626B /* UIImage+WebP.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EDFB911762547C00698166 /* UIImage+WebP.h */; settings = {ATTRIBUTES = (Public, ); }; };
273 438096751CDFC0A100DC626B /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; }; 273 438096751CDFC0A100DC626B /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; };
  274 + 43CE75761CFE9427006C64D0 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
  275 + 43CE75771CFE9427006C64D0 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
  276 + 43CE75781CFE9427006C64D0 /* FLAnimatedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
  277 + 43CE75791CFE9427006C64D0 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */; };
  278 + 43CE757A1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */; };
  279 + 43CE757B1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */; };
  280 + 43CE757C1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
  281 + 43CE757D1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
  282 + 43CE757E1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
  283 + 43CE757F1CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */; };
  284 + 43CE75801CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */; };
  285 + 43CE75811CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */; };
  286 + 43CE75D01CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
  287 + 43CE75D11CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
  288 + 43CE75D21CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
  289 + 43CE75D31CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */; };
  290 + 43CE75D41CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */; };
  291 + 43CE75D51CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */; };
274 4A2CAE041AB4BB5400B6BC39 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; 292 4A2CAE041AB4BB5400B6BC39 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
275 4A2CAE181AB4BB6400B6BC39 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D88148C56230056699D /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; }; 293 4A2CAE181AB4BB6400B6BC39 /* SDWebImageCompat.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D88148C56230056699D /* SDWebImageCompat.h */; settings = {ATTRIBUTES = (Public, ); }; };
276 4A2CAE191AB4BB6400B6BC39 /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 5340674F167780C40042B59E /* SDWebImageCompat.m */; }; 294 4A2CAE191AB4BB6400B6BC39 /* SDWebImageCompat.m in Sources */ = {isa = PBXBuildFile; fileRef = 5340674F167780C40042B59E /* SDWebImageCompat.m */; };
@@ -341,6 +359,12 @@ @@ -341,6 +359,12 @@
341 359
342 /* Begin PBXFileReference section */ 360 /* Begin PBXFileReference section */
343 00733A4C1BC487C000A5A117 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 361 00733A4C1BC487C000A5A117 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  362 + 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = "<group>"; };
  363 + 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImage.m; sourceTree = "<group>"; };
  364 + 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImageView.h; sourceTree = "<group>"; };
  365 + 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = "<group>"; };
  366 + 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FLAnimatedImageView+WebCache.h"; sourceTree = "<group>"; };
  367 + 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "FLAnimatedImageView+WebCache.m"; sourceTree = "<group>"; };
344 4A2CADFF1AB4BB5300B6BC39 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 368 4A2CADFF1AB4BB5300B6BC39 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
345 4A2CAE021AB4BB5400B6BC39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 369 4A2CAE021AB4BB5400B6BC39 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
346 4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImage.h; sourceTree = "<group>"; }; 370 4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImage.h; sourceTree = "<group>"; };
@@ -487,6 +511,35 @@ @@ -487,6 +511,35 @@
487 /* End PBXFrameworksBuildPhase section */ 511 /* End PBXFrameworksBuildPhase section */
488 512
489 /* Begin PBXGroup section */ 513 /* Begin PBXGroup section */
  514 + 43CE75451CFE9427006C64D0 /* FLAnimatedImage */ = {
  515 + isa = PBXGroup;
  516 + children = (
  517 + 43CE75481CFE9427006C64D0 /* FLAnimatedImage */,
  518 + );
  519 + name = FLAnimatedImage;
  520 + path = Vendors/FLAnimatedImage;
  521 + sourceTree = "<group>";
  522 + };
  523 + 43CE75481CFE9427006C64D0 /* FLAnimatedImage */ = {
  524 + isa = PBXGroup;
  525 + children = (
  526 + 43CE75491CFE9427006C64D0 /* FLAnimatedImage.h */,
  527 + 43CE754A1CFE9427006C64D0 /* FLAnimatedImage.m */,
  528 + 43CE754B1CFE9427006C64D0 /* FLAnimatedImageView.h */,
  529 + 43CE754C1CFE9427006C64D0 /* FLAnimatedImageView.m */,
  530 + );
  531 + path = FLAnimatedImage;
  532 + sourceTree = "<group>";
  533 + };
  534 + 43CE75CD1CFE98B3006C64D0 /* FLAnimatedImage */ = {
  535 + isa = PBXGroup;
  536 + children = (
  537 + 43CE75CE1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h */,
  538 + 43CE75CF1CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m */,
  539 + );
  540 + path = FLAnimatedImage;
  541 + sourceTree = "<group>";
  542 + };
490 4A2CAE001AB4BB5300B6BC39 /* WebImage */ = { 543 4A2CAE001AB4BB5300B6BC39 /* WebImage */ = {
491 isa = PBXGroup; 544 isa = PBXGroup;
492 children = ( 545 children = (
@@ -528,6 +581,7 @@ @@ -528,6 +581,7 @@
528 53922D71148C55820056699D /* Frameworks */ = { 581 53922D71148C55820056699D /* Frameworks */ = {
529 isa = PBXGroup; 582 isa = PBXGroup;
530 children = ( 583 children = (
  584 + 43CE75451CFE9427006C64D0 /* FLAnimatedImage */,
531 DA577C121998E60B007367ED /* libwebp */, 585 DA577C121998E60B007367ED /* libwebp */,
532 53FB893F14D35D1A0020B787 /* CoreGraphics.framework */, 586 53FB893F14D35D1A0020B787 /* CoreGraphics.framework */,
533 53922D72148C55820056699D /* Foundation.framework */, 587 53922D72148C55820056699D /* Foundation.framework */,
@@ -546,6 +600,7 @@ @@ -546,6 +600,7 @@
546 53922DAA148C56470056699D /* Cache */, 600 53922DAA148C56470056699D /* Cache */,
547 53922DAC148C56DD0056699D /* Utils */, 601 53922DAC148C56DD0056699D /* Utils */,
548 53922DA9148C562D0056699D /* Categories */, 602 53922DA9148C562D0056699D /* Categories */,
  603 + 43CE75CD1CFE98B3006C64D0 /* FLAnimatedImage */,
549 ); 604 );
550 path = SDWebImage; 605 path = SDWebImage;
551 sourceTree = "<group>"; 606 sourceTree = "<group>";
@@ -758,6 +813,7 @@ @@ -758,6 +813,7 @@
758 00733A6C1BC4880E00A5A117 /* UIButton+WebCache.h in Headers */, 813 00733A6C1BC4880E00A5A117 /* UIButton+WebCache.h in Headers */,
759 431738DF1CDFC8A40008FEB9 /* vp8li.h in Headers */, 814 431738DF1CDFC8A40008FEB9 /* vp8li.h in Headers */,
760 4317395B1CDFC8B70008FEB9 /* types.h in Headers */, 815 4317395B1CDFC8B70008FEB9 /* types.h in Headers */,
  816 + 43CE75D21CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
761 431739551CDFC8B70008FEB9 /* decode.h in Headers */, 817 431739551CDFC8B70008FEB9 /* decode.h in Headers */,
762 00733A731BC4880E00A5A117 /* SDWebImage.h in Headers */, 818 00733A731BC4880E00A5A117 /* SDWebImage.h in Headers */,
763 00733A701BC4880E00A5A117 /* UIImageView+HighlightedWebCache.h in Headers */, 819 00733A701BC4880E00A5A117 /* UIImageView+HighlightedWebCache.h in Headers */,
@@ -778,8 +834,10 @@ @@ -778,8 +834,10 @@
778 431738D41CDFC8A40008FEB9 /* alphai.h in Headers */, 834 431738D41CDFC8A40008FEB9 /* alphai.h in Headers */,
779 431739581CDFC8B70008FEB9 /* format_constants.h in Headers */, 835 431739581CDFC8B70008FEB9 /* format_constants.h in Headers */,
780 431739491CDFC8B20008FEB9 /* rescaler.h in Headers */, 836 431739491CDFC8B20008FEB9 /* rescaler.h in Headers */,
  837 + 43CE75781CFE9427006C64D0 /* FLAnimatedImage.h in Headers */,
781 431739161CDFC8AA0008FEB9 /* yuv.h in Headers */, 838 431739161CDFC8AA0008FEB9 /* yuv.h in Headers */,
782 00733A6E1BC4880E00A5A117 /* UIImage+MultiFormat.h in Headers */, 839 00733A6E1BC4880E00A5A117 /* UIImage+MultiFormat.h in Headers */,
  840 + 43CE757E1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
783 431738DD1CDFC8A40008FEB9 /* vp8i.h in Headers */, 841 431738DD1CDFC8A40008FEB9 /* vp8i.h in Headers */,
784 00733A6D1BC4880E00A5A117 /* UIImage+GIF.h in Headers */, 842 00733A6D1BC4880E00A5A117 /* UIImage+GIF.h in Headers */,
785 00733A651BC4880E00A5A117 /* SDWebImageDownloader.h in Headers */, 843 00733A651BC4880E00A5A117 /* SDWebImageDownloader.h in Headers */,
@@ -796,6 +854,7 @@ @@ -796,6 +854,7 @@
796 files = ( 854 files = (
797 4317394F1CDFC8B70008FEB9 /* demux.h in Headers */, 855 4317394F1CDFC8B70008FEB9 /* demux.h in Headers */,
798 431739211CDFC8B20008FEB9 /* endian_inl.h in Headers */, 856 431739211CDFC8B20008FEB9 /* endian_inl.h in Headers */,
  857 + 43CE757D1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
799 431739541CDFC8B70008FEB9 /* types.h in Headers */, 858 431739541CDFC8B70008FEB9 /* types.h in Headers */,
800 431738F51CDFC8AA0008FEB9 /* neon.h in Headers */, 859 431738F51CDFC8AA0008FEB9 /* neon.h in Headers */,
801 431738C51CDFC8A30008FEB9 /* alphai.h in Headers */, 860 431738C51CDFC8A30008FEB9 /* alphai.h in Headers */,
@@ -809,6 +868,7 @@ @@ -809,6 +868,7 @@
809 4317392F1CDFC8B20008FEB9 /* rescaler.h in Headers */, 868 4317392F1CDFC8B20008FEB9 /* rescaler.h in Headers */,
810 4A2CAE181AB4BB6400B6BC39 /* SDWebImageCompat.h in Headers */, 869 4A2CAE181AB4BB6400B6BC39 /* SDWebImageCompat.h in Headers */,
811 4317391B1CDFC8B20008FEB9 /* bit_reader.h in Headers */, 870 4317391B1CDFC8B20008FEB9 /* bit_reader.h in Headers */,
  871 + 43CE75D11CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
812 4A2CAE331AB4BB7500B6BC39 /* UIImageView+HighlightedWebCache.h in Headers */, 872 4A2CAE331AB4BB7500B6BC39 /* UIImageView+HighlightedWebCache.h in Headers */,
813 431739521CDFC8B70008FEB9 /* mux.h in Headers */, 873 431739521CDFC8B70008FEB9 /* mux.h in Headers */,
814 431738F11CDFC8AA0008FEB9 /* lossless.h in Headers */, 874 431738F11CDFC8AA0008FEB9 /* lossless.h in Headers */,
@@ -821,6 +881,7 @@ @@ -821,6 +881,7 @@
821 431739291CDFC8B20008FEB9 /* quant_levels.h in Headers */, 881 431739291CDFC8B20008FEB9 /* quant_levels.h in Headers */,
822 4317391C1CDFC8B20008FEB9 /* bit_reader_inl.h in Headers */, 882 4317391C1CDFC8B20008FEB9 /* bit_reader_inl.h in Headers */,
823 4317392B1CDFC8B20008FEB9 /* quant_levels_dec.h in Headers */, 883 4317392B1CDFC8B20008FEB9 /* quant_levels_dec.h in Headers */,
  884 + 43CE75771CFE9427006C64D0 /* FLAnimatedImage.h in Headers */,
824 4A2CAE2B1AB4BB7500B6BC39 /* UIButton+WebCache.h in Headers */, 885 4A2CAE2B1AB4BB7500B6BC39 /* UIButton+WebCache.h in Headers */,
825 4A2CAE251AB4BB7000B6BC39 /* SDWebImagePrefetcher.h in Headers */, 886 4A2CAE251AB4BB7000B6BC39 /* SDWebImagePrefetcher.h in Headers */,
826 4A2CAE371AB4BB7500B6BC39 /* UIView+WebCacheOperation.h in Headers */, 887 4A2CAE371AB4BB7500B6BC39 /* UIView+WebCacheOperation.h in Headers */,
@@ -869,6 +930,7 @@ @@ -869,6 +930,7 @@
869 53761318155AD0D5005750A4 /* SDWebImageCompat.h in Headers */, 930 53761318155AD0D5005750A4 /* SDWebImageCompat.h in Headers */,
870 431738841CDFC2580008FEB9 /* vp8li.h in Headers */, 931 431738841CDFC2580008FEB9 /* vp8li.h in Headers */,
871 431738C31CDFC2660008FEB9 /* types.h in Headers */, 932 431738C31CDFC2660008FEB9 /* types.h in Headers */,
  933 + 43CE75D01CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.h in Headers */,
872 431738BD1CDFC2660008FEB9 /* decode.h in Headers */, 934 431738BD1CDFC2660008FEB9 /* decode.h in Headers */,
873 53761319155AD0D5005750A4 /* SDWebImageDecoder.h in Headers */, 935 53761319155AD0D5005750A4 /* SDWebImageDecoder.h in Headers */,
874 5376131A155AD0D5005750A4 /* SDWebImageDownloader.h in Headers */, 936 5376131A155AD0D5005750A4 /* SDWebImageDownloader.h in Headers */,
@@ -889,8 +951,10 @@ @@ -889,8 +951,10 @@
889 431738791CDFC2580008FEB9 /* alphai.h in Headers */, 951 431738791CDFC2580008FEB9 /* alphai.h in Headers */,
890 431738C01CDFC2660008FEB9 /* format_constants.h in Headers */, 952 431738C01CDFC2660008FEB9 /* format_constants.h in Headers */,
891 431738B81CDFC2630008FEB9 /* rescaler.h in Headers */, 953 431738B81CDFC2630008FEB9 /* rescaler.h in Headers */,
  954 + 43CE75761CFE9427006C64D0 /* FLAnimatedImage.h in Headers */,
892 4317389F1CDFC25E0008FEB9 /* yuv.h in Headers */, 955 4317389F1CDFC25E0008FEB9 /* yuv.h in Headers */,
893 438096721CDFC08200DC626B /* MKAnnotationView+WebCache.h in Headers */, 956 438096721CDFC08200DC626B /* MKAnnotationView+WebCache.h in Headers */,
  957 + 43CE757C1CFE9427006C64D0 /* FLAnimatedImageView.h in Headers */,
894 431738821CDFC2580008FEB9 /* vp8i.h in Headers */, 958 431738821CDFC2580008FEB9 /* vp8i.h in Headers */,
895 AB615303192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */, 959 AB615303192DA24600A2D8E9 /* UIView+WebCacheOperation.h in Headers */,
896 A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */, 960 A18A6CC7172DC28500419892 /* UIImage+GIF.h in Headers */,
@@ -1038,6 +1102,7 @@ @@ -1038,6 +1102,7 @@
1038 431739391CDFC8B20008FEB9 /* color_cache.c in Sources */, 1102 431739391CDFC8B20008FEB9 /* color_cache.c in Sources */,
1039 00733A5A1BC4880000A5A117 /* SDWebImagePrefetcher.m in Sources */, 1103 00733A5A1BC4880000A5A117 /* SDWebImagePrefetcher.m in Sources */,
1040 431739031CDFC8AA0008FEB9 /* dec_mips32.c in Sources */, 1104 431739031CDFC8AA0008FEB9 /* dec_mips32.c in Sources */,
  1105 + 43CE75D51CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
1041 4317390B1CDFC8AA0008FEB9 /* enc_sse2.c in Sources */, 1106 4317390B1CDFC8AA0008FEB9 /* enc_sse2.c in Sources */,
1042 00733A5B1BC4880000A5A117 /* NSData+ImageContentType.m in Sources */, 1107 00733A5B1BC4880000A5A117 /* NSData+ImageContentType.m in Sources */,
1043 431739131CDFC8AA0008FEB9 /* upsampling_neon.c in Sources */, 1108 431739131CDFC8AA0008FEB9 /* upsampling_neon.c in Sources */,
@@ -1074,6 +1139,7 @@ @@ -1074,6 +1139,7 @@
1074 4317393C1CDFC8B20008FEB9 /* filters.c in Sources */, 1139 4317393C1CDFC8B20008FEB9 /* filters.c in Sources */,
1075 431738DA1CDFC8A40008FEB9 /* quant.c in Sources */, 1140 431738DA1CDFC8A40008FEB9 /* quant.c in Sources */,
1076 00733A591BC4880000A5A117 /* SDWebImageDecoder.m in Sources */, 1141 00733A591BC4880000A5A117 /* SDWebImageDecoder.m in Sources */,
  1142 + 43CE75811CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */,
1077 00733A5F1BC4880000A5A117 /* UIImage+WebP.m in Sources */, 1143 00733A5F1BC4880000A5A117 /* UIImage+WebP.m in Sources */,
1078 431739041CDFC8AA0008FEB9 /* dec_neon.c in Sources */, 1144 431739041CDFC8AA0008FEB9 /* dec_neon.c in Sources */,
1079 431739441CDFC8B20008FEB9 /* quant_levels_dec.c in Sources */, 1145 431739441CDFC8B20008FEB9 /* quant_levels_dec.c in Sources */,
@@ -1083,6 +1149,7 @@ @@ -1083,6 +1149,7 @@
1083 431739141CDFC8AA0008FEB9 /* upsampling_sse2.c in Sources */, 1149 431739141CDFC8AA0008FEB9 /* upsampling_sse2.c in Sources */,
1084 00733A5D1BC4880000A5A117 /* UIImage+GIF.m in Sources */, 1150 00733A5D1BC4880000A5A117 /* UIImage+GIF.m in Sources */,
1085 431738DC1CDFC8A40008FEB9 /* vp8.c in Sources */, 1151 431738DC1CDFC8A40008FEB9 /* vp8.c in Sources */,
  1152 + 43CE757B1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
1086 00733A571BC4880000A5A117 /* SDImageCache.m in Sources */, 1153 00733A571BC4880000A5A117 /* SDImageCache.m in Sources */,
1087 4317394A1CDFC8B20008FEB9 /* thread.c in Sources */, 1154 4317394A1CDFC8B20008FEB9 /* thread.c in Sources */,
1088 431739051CDFC8AA0008FEB9 /* dec_sse2.c in Sources */, 1155 431739051CDFC8AA0008FEB9 /* dec_sse2.c in Sources */,
@@ -1109,6 +1176,7 @@ @@ -1109,6 +1176,7 @@
1109 4A2CAE2E1AB4BB7500B6BC39 /* UIImage+GIF.m in Sources */, 1176 4A2CAE2E1AB4BB7500B6BC39 /* UIImage+GIF.m in Sources */,
1110 4A2CAE321AB4BB7500B6BC39 /* UIImage+WebP.m in Sources */, 1177 4A2CAE321AB4BB7500B6BC39 /* UIImage+WebP.m in Sources */,
1111 431738EC1CDFC8AA0008FEB9 /* enc_avx2.c in Sources */, 1178 431738EC1CDFC8AA0008FEB9 /* enc_avx2.c in Sources */,
  1179 + 43CE75D41CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
1112 4317392E1CDFC8B20008FEB9 /* rescaler.c in Sources */, 1180 4317392E1CDFC8B20008FEB9 /* rescaler.c in Sources */,
1113 431738E91CDFC8AA0008FEB9 /* dec_sse2.c in Sources */, 1181 431738E91CDFC8AA0008FEB9 /* dec_sse2.c in Sources */,
1114 431738F71CDFC8AA0008FEB9 /* upsampling_neon.c in Sources */, 1182 431738F71CDFC8AA0008FEB9 /* upsampling_neon.c in Sources */,
@@ -1118,6 +1186,7 @@ @@ -1118,6 +1186,7 @@
1118 431738F41CDFC8AA0008FEB9 /* lossless_sse2.c in Sources */, 1186 431738F41CDFC8AA0008FEB9 /* lossless_sse2.c in Sources */,
1119 431738EF1CDFC8AA0008FEB9 /* enc_sse2.c in Sources */, 1187 431738EF1CDFC8AA0008FEB9 /* enc_sse2.c in Sources */,
1120 431739301CDFC8B20008FEB9 /* thread.c in Sources */, 1188 431739301CDFC8B20008FEB9 /* thread.c in Sources */,
  1189 + 43CE757A1CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
1121 4A2CAE361AB4BB7500B6BC39 /* UIImageView+WebCache.m in Sources */, 1190 4A2CAE361AB4BB7500B6BC39 /* UIImageView+WebCache.m in Sources */,
1122 431739221CDFC8B20008FEB9 /* filters.c in Sources */, 1191 431739221CDFC8B20008FEB9 /* filters.c in Sources */,
1123 431738FB1CDFC8AA0008FEB9 /* yuv_mips32.c in Sources */, 1192 431738FB1CDFC8AA0008FEB9 /* yuv_mips32.c in Sources */,
@@ -1155,6 +1224,7 @@ @@ -1155,6 +1224,7 @@
1155 4A2CAE341AB4BB7500B6BC39 /* UIImageView+HighlightedWebCache.m in Sources */, 1224 4A2CAE341AB4BB7500B6BC39 /* UIImageView+HighlightedWebCache.m in Sources */,
1156 431738F81CDFC8AA0008FEB9 /* upsampling_sse2.c in Sources */, 1225 431738F81CDFC8AA0008FEB9 /* upsampling_sse2.c in Sources */,
1157 4A2CAE201AB4BB6C00B6BC39 /* SDImageCache.m in Sources */, 1226 4A2CAE201AB4BB6C00B6BC39 /* SDImageCache.m in Sources */,
  1227 + 43CE75801CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */,
1158 431738C81CDFC8A30008FEB9 /* frame.c in Sources */, 1228 431738C81CDFC8A30008FEB9 /* frame.c in Sources */,
1159 4317391A1CDFC8B20008FEB9 /* bit_reader.c in Sources */, 1229 4317391A1CDFC8B20008FEB9 /* bit_reader.c in Sources */,
1160 431738E81CDFC8AA0008FEB9 /* dec_neon.c in Sources */, 1230 431738E81CDFC8AA0008FEB9 /* dec_neon.c in Sources */,
@@ -1177,6 +1247,7 @@ @@ -1177,6 +1247,7 @@
1177 53761309155AD0D5005750A4 /* SDImageCache.m in Sources */, 1247 53761309155AD0D5005750A4 /* SDImageCache.m in Sources */,
1178 5376130A155AD0D5005750A4 /* SDWebImageDecoder.m in Sources */, 1248 5376130A155AD0D5005750A4 /* SDWebImageDecoder.m in Sources */,
1179 431738911CDFC25E0008FEB9 /* enc_avx2.c in Sources */, 1249 431738911CDFC25E0008FEB9 /* enc_avx2.c in Sources */,
  1250 + 43CE75D31CFE98E0006C64D0 /* FLAnimatedImageView+WebCache.m in Sources */,
1180 431738B71CDFC2630008FEB9 /* rescaler.c in Sources */, 1251 431738B71CDFC2630008FEB9 /* rescaler.c in Sources */,
1181 4317388E1CDFC25E0008FEB9 /* dec_sse2.c in Sources */, 1252 4317388E1CDFC25E0008FEB9 /* dec_sse2.c in Sources */,
1182 4317389C1CDFC25E0008FEB9 /* upsampling_neon.c in Sources */, 1253 4317389C1CDFC25E0008FEB9 /* upsampling_neon.c in Sources */,
@@ -1186,6 +1257,7 @@ @@ -1186,6 +1257,7 @@
1186 431738991CDFC25E0008FEB9 /* lossless_sse2.c in Sources */, 1257 431738991CDFC25E0008FEB9 /* lossless_sse2.c in Sources */,
1187 431738941CDFC25E0008FEB9 /* enc_sse2.c in Sources */, 1258 431738941CDFC25E0008FEB9 /* enc_sse2.c in Sources */,
1188 431738B91CDFC2630008FEB9 /* thread.c in Sources */, 1259 431738B91CDFC2630008FEB9 /* thread.c in Sources */,
  1260 + 43CE75791CFE9427006C64D0 /* FLAnimatedImage.m in Sources */,
1189 5376130B155AD0D5005750A4 /* SDWebImageDownloader.m in Sources */, 1261 5376130B155AD0D5005750A4 /* SDWebImageDownloader.m in Sources */,
1190 431738AB1CDFC2630008FEB9 /* filters.c in Sources */, 1262 431738AB1CDFC2630008FEB9 /* filters.c in Sources */,
1191 431738A01CDFC25E0008FEB9 /* yuv_mips32.c in Sources */, 1263 431738A01CDFC25E0008FEB9 /* yuv_mips32.c in Sources */,
@@ -1223,6 +1295,7 @@ @@ -1223,6 +1295,7 @@
1223 53EDFB8C17623F7C00698166 /* UIImage+MultiFormat.m in Sources */, 1295 53EDFB8C17623F7C00698166 /* UIImage+MultiFormat.m in Sources */,
1224 4317389D1CDFC25E0008FEB9 /* upsampling_sse2.c in Sources */, 1296 4317389D1CDFC25E0008FEB9 /* upsampling_sse2.c in Sources */,
1225 ABBE71A818C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m in Sources */, 1297 ABBE71A818C43B4D00B75E91 /* UIImageView+HighlightedWebCache.m in Sources */,
  1298 + 43CE757F1CFE9427006C64D0 /* FLAnimatedImageView.m in Sources */,
1226 4317387C1CDFC2580008FEB9 /* frame.c in Sources */, 1299 4317387C1CDFC2580008FEB9 /* frame.c in Sources */,
1227 431738A31CDFC2630008FEB9 /* bit_reader.c in Sources */, 1300 431738A31CDFC2630008FEB9 /* bit_reader.c in Sources */,
1228 4317388D1CDFC25E0008FEB9 /* dec_neon.c in Sources */, 1301 4317388D1CDFC25E0008FEB9 /* dec_neon.c in Sources */,
  1 +/*
  2 + * This file is part of the SDWebImage package.
  3 + * (c) Olivier Poitrey <rs@dailymotion.com>
  4 + *
  5 + * For the full copyright and license information, please view the LICENSE
  6 + * file that was distributed with this source code.
  7 + */
  8 +
  9 +
  10 +#if COCOAPODS
  11 + @import FLAnimatedImage;
  12 +#else
  13 + #import "FLAnimatedImageView.h"
  14 +#endif
  15 +
  16 +#import "SDWebImageManager.h"
  17 +
  18 +
  19 +/**
  20 + * A category for the FLAnimatedImage imageView class that hooks it to the SDWebImage system.
  21 + * Very similar to the base class category (UIImageView (WebCache))
  22 + */
  23 +@interface FLAnimatedImageView (WebCache)
  24 +
  25 +/**
  26 + * Get the current image URL.
  27 + *
  28 + * Note that because of the limitations of categories this property can get out of sync
  29 + * if you use setImage: directly.
  30 + */
  31 +- (nullable NSURL *)sd_imageURL;
  32 +
  33 +/**
  34 + * 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
  35 + * The download is asynchronous and cached.
  36 + *
  37 + * @param url The url for the image.
  38 + */
  39 +- (void)sd_setImageWithURL:(nullable NSURL *)url;
  40 +
  41 +/**
  42 + * 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
  43 + * The download is asynchronous and cached.
  44 + * Uses a placeholder until the request finishes.
  45 + *
  46 + * @param url The url for the image.
  47 + * @param placeholder The image to be set initially, until the image request finishes.
  48 + */
  49 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  50 + placeholderImage:(nullable UIImage *)placeholder;
  51 +
  52 +/**
  53 + * 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
  54 + * The download is asynchronous and cached.
  55 + * Uses a placeholder until the request finishes.
  56 + *
  57 + * @param url The url for the image.
  58 + * @param placeholder The image to be set initially, until the image request finishes.
  59 + * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
  60 + */
  61 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  62 + placeholderImage:(nullable UIImage *)placeholder
  63 + options:(SDWebImageOptions)options;
  64 +
  65 +/**
  66 + * 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
  67 + * The download is asynchronous and cached.
  68 + *
  69 + * @param url The url for the image.
  70 + * @param completedBlock A block called when operation has been completed. This block has no return value
  71 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  72 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  73 + * indicating if the image was retrieved from the local cache or from the network.
  74 + * The fourth parameter is the original image url.
  75 + */
  76 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  77 + completed:(nullable SDExternalCompletionBlock)completedBlock;
  78 +
  79 +/**
  80 + * 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
  81 + * The download is asynchronous and cached.
  82 + * Uses a placeholder until the request finishes.
  83 + *
  84 + * @param url The url for the image.
  85 + * @param placeholder The image to be set initially, until the image request finishes.
  86 + * @param completedBlock A block called when operation has been completed. This block has no return value
  87 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  88 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  89 + * indicating if the image was retrieved from the local cache or from the network.
  90 + * The fourth parameter is the original image url.
  91 + */
  92 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  93 + placeholderImage:(nullable UIImage *)placeholder
  94 + completed:(nullable SDExternalCompletionBlock)completedBlock;
  95 +
  96 +/**
  97 + * 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
  98 + * The download is asynchronous and cached.
  99 + * Uses a placeholder until the request finishes.
  100 + *
  101 + * @param url The url for the image.
  102 + * @param placeholder The image to be set initially, until the image request finishes.
  103 + * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
  104 + * @param completedBlock A block called when operation has been completed. This block has no return value
  105 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  106 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  107 + * indicating if the image was retrieved from the local cache or from the network.
  108 + * The fourth parameter is the original image url.
  109 + */
  110 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  111 + placeholderImage:(nullable UIImage *)placeholder
  112 + options:(SDWebImageOptions)options
  113 + completed:(nullable SDExternalCompletionBlock)completedBlock;
  114 +
  115 +/**
  116 + * 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
  117 + * The download is asynchronous and cached.
  118 + * Uses a placeholder until the request finishes.
  119 + *
  120 + * @param url The url for the image.
  121 + * @param placeholder The image to be set initially, until the image request finishes.
  122 + * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
  123 + * @param progressBlock A block called while image is downloading
  124 + * @param completedBlock A block called when operation has been completed. This block has no return value
  125 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  126 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  127 + * indicating if the image was retrieved from the local cache or from the network.
  128 + * The fourth parameter is the original image url.
  129 + */
  130 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  131 + placeholderImage:(nullable UIImage *)placeholder
  132 + options:(SDWebImageOptions)options
  133 + progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
  134 + completed:(nullable SDExternalCompletionBlock)completedBlock;
  135 +
  136 +/**
  137 + * Cancel the image load
  138 + */
  139 +- (void)sd_cancelCurrentImageLoad;
  140 +
  141 +@end
  1 +/*
  2 + * This file is part of the SDWebImage package.
  3 + * (c) Olivier Poitrey <rs@dailymotion.com>
  4 + *
  5 + * For the full copyright and license information, please view the LICENSE
  6 + * file that was distributed with this source code.
  7 + */
  8 +
  9 +
  10 +#import "FLAnimatedImageView+WebCache.h"
  11 +#import "objc/runtime.h"
  12 +#import "UIView+WebCacheOperation.h"
  13 +#import "NSData+ImageContentType.h"
  14 +#import "FLAnimatedImage.h"
  15 +#import "UIImageView+WebCache.h"
  16 +
  17 +static char imageURLKey;
  18 +
  19 +
  20 +@implementation FLAnimatedImageView (WebCache)
  21 +
  22 +- (nullable NSURL *)sd_imageURL {
  23 + return objc_getAssociatedObject(self, &imageURLKey);
  24 +}
  25 +
  26 +- (void)sd_setImageWithURL:(nullable NSURL *)url {
  27 + [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
  28 +}
  29 +
  30 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
  31 + [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
  32 +}
  33 +
  34 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
  35 + [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
  36 +}
  37 +
  38 +- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
  39 + [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
  40 +}
  41 +
  42 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
  43 + [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
  44 +}
  45 +
  46 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
  47 + [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
  48 +}
  49 +
  50 +- (void)sd_setImageWithURL:(nullable NSURL *)url
  51 + placeholderImage:(nullable UIImage *)placeholder
  52 + options:(SDWebImageOptions)options
  53 + progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
  54 + completed:(nullable SDExternalCompletionBlock)completedBlock {
  55 + [self sd_cancelCurrentImageLoad];
  56 + objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  57 +
  58 + if (!(options & SDWebImageDelayPlaceholder)) {
  59 + dispatch_main_async_safe(^{
  60 + self.image = placeholder;
  61 + });
  62 + }
  63 +
  64 + if (url) {
  65 + // check if activityView is enabled or not
  66 + if ([self showActivityIndicatorView]) {
  67 + [self addActivityIndicator];
  68 + }
  69 +
  70 + __weak __typeof(self)wself = self;
  71 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
  72 + if (!wself) return;
  73 + dispatch_main_sync_safe(^{
  74 + [wself removeActivityIndicator];
  75 +
  76 + if (!wself) return;
  77 + if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) {
  78 + completedBlock(image, error, cacheType, url);
  79 + return;
  80 + } else if (image) {
  81 + NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
  82 + if ([imageContentType isEqualToString:@"image/gif"]) {
  83 + wself.animatedImage = [FLAnimatedImage animatedImageWithGIFData:data];
  84 + wself.image = nil;
  85 + } else {
  86 + wself.image = image;
  87 + wself.animatedImage = nil;
  88 + }
  89 + [wself setNeedsLayout];
  90 + } else {
  91 + if ((options & SDWebImageDelayPlaceholder)) {
  92 + wself.image = placeholder;
  93 + [wself setNeedsLayout];
  94 + }
  95 + }
  96 + if (completedBlock && finished) {
  97 + completedBlock(image, error, cacheType, url);
  98 + }
  99 + });
  100 + }];
  101 + [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
  102 + } else {
  103 + dispatch_main_async_safe(^{
  104 + [self removeActivityIndicator];
  105 +
  106 + if (completedBlock) {
  107 + NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
  108 + completedBlock(nil, error, SDImageCacheTypeNone, url);
  109 + }
  110 + });
  111 + }
  112 +}
  113 +
  114 +- (void)sd_cancelCurrentImageLoad {
  115 + [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"];
  116 +}
  117 +
  118 +
  119 +@end
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 * Get the current image URL. 18 * Get the current image URL.
19 * 19 *
20 * Note that because of the limitations of categories this property can get out of sync 20 * Note that because of the limitations of categories this property can get out of sync
21 - * if you use sd_setImage: directly. 21 + * if you use setImage: directly.
22 */ 22 */
23 - (nullable NSURL *)sd_imageURL; 23 - (nullable NSURL *)sd_imageURL;
24 24
@@ -70,7 +70,7 @@ @@ -70,7 +70,7 @@
70 * The fourth parameter is the original image url. 70 * The fourth parameter is the original image url.
71 */ 71 */
72 - (void)sd_setImageWithURL:(nullable NSURL *)url 72 - (void)sd_setImageWithURL:(nullable NSURL *)url
73 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 73 + completed:(nullable SDExternalCompletionBlock)completedBlock;
74 74
75 /** 75 /**
76 * Set the imageView `image` with an `url`, placeholder. 76 * Set the imageView `image` with an `url`, placeholder.
@@ -87,7 +87,7 @@ @@ -87,7 +87,7 @@
87 */ 87 */
88 - (void)sd_setImageWithURL:(nullable NSURL *)url 88 - (void)sd_setImageWithURL:(nullable NSURL *)url
89 placeholderImage:(nullable UIImage *)placeholder 89 placeholderImage:(nullable UIImage *)placeholder
90 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 90 + completed:(nullable SDExternalCompletionBlock)completedBlock;
91 91
92 /** 92 /**
93 * Set the imageView `image` with an `url`, placeholder and custom options. 93 * Set the imageView `image` with an `url`, placeholder and custom options.
@@ -106,7 +106,7 @@ @@ -106,7 +106,7 @@
106 - (void)sd_setImageWithURL:(nullable NSURL *)url 106 - (void)sd_setImageWithURL:(nullable NSURL *)url
107 placeholderImage:(nullable UIImage *)placeholder 107 placeholderImage:(nullable UIImage *)placeholder
108 options:(SDWebImageOptions)options 108 options:(SDWebImageOptions)options
109 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 109 + completed:(nullable SDExternalCompletionBlock)completedBlock;
110 110
111 /** 111 /**
112 * Cancel the current download 112 * Cancel the current download
@@ -30,18 +30,18 @@ static char imageURLKey; @@ -30,18 +30,18 @@ static char imageURLKey;
30 [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil]; 30 [self sd_setImageWithURL:url placeholderImage:placeholder options:options completed:nil];
31 } 31 }
32 32
33 -- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDWebImageCompletionBlock)completedBlock { 33 +- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
34 [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:completedBlock]; 34 [self sd_setImageWithURL:url placeholderImage:nil options:0 completed:completedBlock];
35 } 35 }
36 36
37 -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock { 37 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
38 [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:completedBlock]; 38 [self sd_setImageWithURL:url placeholderImage:placeholder options:0 completed:completedBlock];
39 } 39 }
40 40
41 - (void)sd_setImageWithURL:(nullable NSURL *)url 41 - (void)sd_setImageWithURL:(nullable NSURL *)url
42 placeholderImage:(nullable UIImage *)placeholder 42 placeholderImage:(nullable UIImage *)placeholder
43 options:(SDWebImageOptions)options 43 options:(SDWebImageOptions)options
44 - completed:(nullable SDWebImageCompletionBlock)completedBlock { 44 + completed:(nullable SDExternalCompletionBlock)completedBlock {
45 [self sd_cancelCurrentImageLoad]; 45 [self sd_cancelCurrentImageLoad];
46 46
47 objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 47 objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
@@ -49,7 +49,7 @@ static char imageURLKey; @@ -49,7 +49,7 @@ static char imageURLKey;
49 49
50 if (url) { 50 if (url) {
51 __weak __typeof(self)wself = self; 51 __weak __typeof(self)wself = self;
52 - id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 52 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
53 if (!wself) return; 53 if (!wself) return;
54 dispatch_main_sync_safe(^{ 54 dispatch_main_sync_safe(^{
55 __strong MKAnnotationView *sself = wself; 55 __strong MKAnnotationView *sself = wself;
@@ -24,7 +24,7 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) { @@ -24,7 +24,7 @@ typedef NS_ENUM(NSInteger, SDImageCacheType) {
24 SDImageCacheTypeMemory 24 SDImageCacheTypeMemory
25 }; 25 };
26 26
27 -typedef void(^SDWebImageQueryCompletedBlock)(UIImage * _Nullable image, SDImageCacheType cacheType); 27 +typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);
28 28
29 typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache); 29 typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache);
30 30
@@ -148,7 +148,7 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot @@ -148,7 +148,7 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
148 * 148 *
149 * @param key The unique key used to store the wanted image 149 * @param key The unique key used to store the wanted image
150 */ 150 */
151 -- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDWebImageQueryCompletedBlock)doneBlock; 151 +- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock;
152 152
153 /** 153 /**
154 * Query the memory cache synchronously. 154 * Query the memory cache synchronously.
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 #import "SDWebImageDecoder.h" 10 #import "SDWebImageDecoder.h"
11 #import "UIImage+MultiFormat.h" 11 #import "UIImage+MultiFormat.h"
12 #import <CommonCrypto/CommonDigest.h> 12 #import <CommonCrypto/CommonDigest.h>
  13 +#import "UIImage+GIF.h"
13 14
14 // See https://github.com/rs/SDWebImage/pull/1141 for discussion 15 // See https://github.com/rs/SDWebImage/pull/1141 for discussion
15 @interface AutoPurgeCache : NSCache 16 @interface AutoPurgeCache : NSCache
@@ -384,20 +385,24 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { @@ -384,20 +385,24 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
384 return SDScaledImageForKey(key, image); 385 return SDScaledImageForKey(key, image);
385 } 386 }
386 387
387 -- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDWebImageQueryCompletedBlock)doneBlock { 388 +- (nullable NSOperation *)queryDiskCacheForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock {
388 if (!doneBlock) { 389 if (!doneBlock) {
389 return nil; 390 return nil;
390 } 391 }
391 392
392 if (!key) { 393 if (!key) {
393 - doneBlock(nil, SDImageCacheTypeNone); 394 + doneBlock(nil, nil, SDImageCacheTypeNone);
394 return nil; 395 return nil;
395 } 396 }
396 397
397 // First check the in-memory cache... 398 // First check the in-memory cache...
398 UIImage *image = [self imageFromMemoryCacheForKey:key]; 399 UIImage *image = [self imageFromMemoryCacheForKey:key];
399 if (image) { 400 if (image) {
400 - doneBlock(image, SDImageCacheTypeMemory); 401 + NSData *diskData = nil;
  402 + if ([image isGIF]) {
  403 + diskData = [self diskImageDataBySearchingAllPathsForKey:key];
  404 + }
  405 + doneBlock(image, diskData, SDImageCacheTypeMemory);
401 return nil; 406 return nil;
402 } 407 }
403 408
@@ -408,6 +413,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { @@ -408,6 +413,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
408 } 413 }
409 414
410 @autoreleasepool { 415 @autoreleasepool {
  416 + NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];
411 UIImage *diskImage = [self diskImageForKey:key]; 417 UIImage *diskImage = [self diskImageForKey:key];
412 if (diskImage && self.shouldCacheImagesInMemory) { 418 if (diskImage && self.shouldCacheImagesInMemory) {
413 NSUInteger cost = SDCacheCostForImage(diskImage); 419 NSUInteger cost = SDCacheCostForImage(diskImage);
@@ -415,7 +421,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) { @@ -415,7 +421,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
415 } 421 }
416 422
417 dispatch_async(dispatch_get_main_queue(), ^{ 423 dispatch_async(dispatch_get_main_queue(), ^{
418 - doneBlock(diskImage, SDImageCacheTypeDisk); 424 + doneBlock(diskImage, diskData, SDImageCacheTypeDisk);
419 }); 425 });
420 } 426 }
421 }); 427 });
@@ -90,9 +90,9 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { @@ -90,9 +90,9 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
90 SDWebImageAvoidAutoSetImage = 1 << 11 90 SDWebImageAvoidAutoSetImage = 1 << 11
91 }; 91 };
92 92
93 -typedef void(^SDWebImageCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL); 93 +typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
94 94
95 -typedef void(^SDWebImageCompletionWithFinishedBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL); 95 +typedef void(^SDInternalCompletionBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL);
96 96
97 typedef NSString * _Nullable (^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable url); 97 typedef NSString * _Nullable (^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable url);
98 98
@@ -197,22 +197,24 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager]; @@ -197,22 +197,24 @@ SDWebImageManager *manager = [SDWebImageManager sharedManager];
197 * 197 *
198 * This parameter is required. 198 * This parameter is required.
199 * 199 *
200 - * This block has no return value and takes the requested UIImage as first parameter.  
201 - * In case of error the image parameter is nil and the second parameter may contain an NSError. 200 + * This block has no return value and takes the requested UIImage as first parameter and the NSData representation as second parameter.
  201 + * In case of error the image parameter is nil and the third parameter may contain an NSError.
202 * 202 *
203 - * The third parameter is an `SDImageCacheType` enum indicating if the image was retrieved from the local cache 203 + * The forth parameter is an `SDImageCacheType` enum indicating if the image was retrieved from the local cache
204 * or from the memory cache or from the network. 204 * or from the memory cache or from the network.
205 * 205 *
206 - * The last parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is 206 + * The fith parameter is set to NO when the SDWebImageProgressiveDownload option is used and the image is
207 * downloading. This block is thus called repeatedly with a partial image. When image is fully downloaded, the 207 * downloading. This block is thus called repeatedly with a partial image. When image is fully downloaded, the
208 * block is called a last time with the full image and the last parameter set to YES. 208 * block is called a last time with the full image and the last parameter set to YES.
209 * 209 *
  210 + * The last parameter is the original image URL
  211 + *
210 * @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation 212 * @return Returns an NSObject conforming to SDWebImageOperation. Should be an instance of SDWebImageDownloaderOperation
211 */ 213 */
212 - (nullable id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url 214 - (nullable id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
213 options:(SDWebImageOptions)options 215 options:(SDWebImageOptions)options
214 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 216 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
215 - completed:(nullable SDWebImageCompletionWithFinishedBlock)completedBlock; 217 + completed:(nullable SDInternalCompletionBlock)completedBlock;
216 218
217 /** 219 /**
218 * Saves image to cache for given URL 220 * Saves image to cache for given URL
@@ -115,7 +115,7 @@ @@ -115,7 +115,7 @@
115 - (id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url 115 - (id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
116 options:(SDWebImageOptions)options 116 options:(SDWebImageOptions)options
117 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 117 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
118 - completed:(nullable SDWebImageCompletionWithFinishedBlock)completedBlock { 118 + completed:(nullable SDInternalCompletionBlock)completedBlock {
119 // Invoking this method without a completedBlock is pointless 119 // Invoking this method without a completedBlock is pointless
120 NSAssert(completedBlock != nil, @"If you mean to prefetch the image, use -[SDWebImagePrefetcher prefetchURLs] instead"); 120 NSAssert(completedBlock != nil, @"If you mean to prefetch the image, use -[SDWebImagePrefetcher prefetchURLs] instead");
121 121
@@ -143,7 +143,7 @@ @@ -143,7 +143,7 @@
143 if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) { 143 if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
144 dispatch_main_sync_safe(^{ 144 dispatch_main_sync_safe(^{
145 NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]; 145 NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil];
146 - completedBlock(nil, error, SDImageCacheTypeNone, YES, url); 146 + completedBlock(nil, nil, error, SDImageCacheTypeNone, YES, url);
147 }); 147 });
148 return operation; 148 return operation;
149 } 149 }
@@ -153,7 +153,7 @@ @@ -153,7 +153,7 @@
153 } 153 }
154 NSString *key = [self cacheKeyForURL:url]; 154 NSString *key = [self cacheKeyForURL:url];
155 155
156 - operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType) { 156 + operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *cachedImage, NSData *cachedData, SDImageCacheType cacheType) {
157 if (operation.isCancelled) { 157 if (operation.isCancelled) {
158 @synchronized (self.runningOperations) { 158 @synchronized (self.runningOperations) {
159 [self.runningOperations removeObject:operation]; 159 [self.runningOperations removeObject:operation];
@@ -162,12 +162,12 @@ @@ -162,12 +162,12 @@
162 return; 162 return;
163 } 163 }
164 164
165 - if ((!image || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) {  
166 - if (image && options & SDWebImageRefreshCached) { 165 + if ((!cachedImage || options & SDWebImageRefreshCached) && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])) {
  166 + if (cachedImage && options & SDWebImageRefreshCached) {
167 dispatch_main_sync_safe(^{ 167 dispatch_main_sync_safe(^{
168 // If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image 168 // If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image
169 // AND try to re-download it in order to let a chance to NSURLCache to refresh it from server. 169 // AND try to re-download it in order to let a chance to NSURLCache to refresh it from server.
170 - completedBlock(image, nil, cacheType, YES, url); 170 + completedBlock(cachedImage, cachedData, nil, cacheType, YES, url);
171 }); 171 });
172 } 172 }
173 173
@@ -180,23 +180,22 @@ @@ -180,23 +180,22 @@
180 if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies; 180 if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies;
181 if (options & SDWebImageAllowInvalidSSLCertificates) downloaderOptions |= SDWebImageDownloaderAllowInvalidSSLCertificates; 181 if (options & SDWebImageAllowInvalidSSLCertificates) downloaderOptions |= SDWebImageDownloaderAllowInvalidSSLCertificates;
182 if (options & SDWebImageHighPriority) downloaderOptions |= SDWebImageDownloaderHighPriority; 182 if (options & SDWebImageHighPriority) downloaderOptions |= SDWebImageDownloaderHighPriority;
183 - if (image && options & SDWebImageRefreshCached) { 183 + if (cachedImage && options & SDWebImageRefreshCached) {
184 // force progressive off if image already cached but forced refreshing 184 // force progressive off if image already cached but forced refreshing
185 downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload; 185 downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload;
186 // ignore image read from NSURLCache if image if cached but force refreshing 186 // ignore image read from NSURLCache if image if cached but force refreshing
187 downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse; 187 downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
188 } 188 }
189 - id subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished) { 189 + id subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *downloadedData, NSError *error, BOOL finished) {
190 __strong __typeof(weakOperation) strongOperation = weakOperation; 190 __strong __typeof(weakOperation) strongOperation = weakOperation;
191 if (!strongOperation || strongOperation.isCancelled) { 191 if (!strongOperation || strongOperation.isCancelled) {
192 // Do nothing if the operation was cancelled 192 // Do nothing if the operation was cancelled
193 // See #699 for more details 193 // See #699 for more details
194 // 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 194 // 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
195 - }  
196 - else if (error) { 195 + } else if (error) {
197 dispatch_main_sync_safe(^{ 196 dispatch_main_sync_safe(^{
198 if (strongOperation && !strongOperation.isCancelled) { 197 if (strongOperation && !strongOperation.isCancelled) {
199 - completedBlock(nil, error, SDImageCacheTypeNone, finished, url); 198 + completedBlock(nil, nil, error, SDImageCacheTypeNone, finished, url);
200 } 199 }
201 }); 200 });
202 201
@@ -221,33 +220,31 @@ @@ -221,33 +220,31 @@
221 220
222 BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly); 221 BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly);
223 222
224 - if (options & SDWebImageRefreshCached && image && !downloadedImage) { 223 + if (options & SDWebImageRefreshCached && cachedImage && !downloadedImage) {
225 // Image refresh hit the NSURLCache cache, do not call the completion block 224 // Image refresh hit the NSURLCache cache, do not call the completion block
226 - }  
227 - else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) { 225 + } else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) {
228 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 226 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
229 UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url]; 227 UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
230 228
231 if (transformedImage && finished) { 229 if (transformedImage && finished) {
232 BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage]; 230 BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
233 - [self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:(imageWasTransformed ? nil : data) forKey:key toDisk:cacheOnDisk]; 231 + [self.imageCache storeImage:transformedImage recalculateFromImage:imageWasTransformed imageData:(imageWasTransformed ? nil : downloadedData) forKey:key toDisk:cacheOnDisk];
234 } 232 }
235 233
236 dispatch_main_sync_safe(^{ 234 dispatch_main_sync_safe(^{
237 if (strongOperation && !strongOperation.isCancelled) { 235 if (strongOperation && !strongOperation.isCancelled) {
238 - completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished, url); 236 + completedBlock(transformedImage, downloadedData, nil, SDImageCacheTypeNone, finished, url);
239 } 237 }
240 }); 238 });
241 }); 239 });
242 - }  
243 - else { 240 + } else {
244 if (downloadedImage && finished) { 241 if (downloadedImage && finished) {
245 - [self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:data forKey:key toDisk:cacheOnDisk]; 242 + [self.imageCache storeImage:downloadedImage recalculateFromImage:NO imageData:downloadedData forKey:key toDisk:cacheOnDisk];
246 } 243 }
247 244
248 dispatch_main_sync_safe(^{ 245 dispatch_main_sync_safe(^{
249 if (strongOperation && !strongOperation.isCancelled) { 246 if (strongOperation && !strongOperation.isCancelled) {
250 - completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished, url); 247 + completedBlock(downloadedImage, downloadedData, nil, SDImageCacheTypeNone, finished, url);
251 } 248 }
252 }); 249 });
253 } 250 }
@@ -271,24 +268,22 @@ @@ -271,24 +268,22 @@
271 } 268 }
272 } 269 }
273 }; 270 };
274 - }  
275 - else if (image) { 271 + } else if (cachedImage) {
276 dispatch_main_sync_safe(^{ 272 dispatch_main_sync_safe(^{
277 __strong __typeof(weakOperation) strongOperation = weakOperation; 273 __strong __typeof(weakOperation) strongOperation = weakOperation;
278 if (strongOperation && !strongOperation.isCancelled) { 274 if (strongOperation && !strongOperation.isCancelled) {
279 - completedBlock(image, nil, cacheType, YES, url); 275 + completedBlock(cachedImage, cachedData, nil, cacheType, YES, url);
280 } 276 }
281 }); 277 });
282 @synchronized (self.runningOperations) { 278 @synchronized (self.runningOperations) {
283 [self.runningOperations removeObject:operation]; 279 [self.runningOperations removeObject:operation];
284 } 280 }
285 - }  
286 - else { 281 + } else {
287 // Image not in cache and download disallowed by delegate 282 // Image not in cache and download disallowed by delegate
288 dispatch_main_sync_safe(^{ 283 dispatch_main_sync_safe(^{
289 __strong __typeof(weakOperation) strongOperation = weakOperation; 284 __strong __typeof(weakOperation) strongOperation = weakOperation;
290 if (strongOperation && !weakOperation.isCancelled) { 285 if (strongOperation && !weakOperation.isCancelled) {
291 - completedBlock(nil, nil, SDImageCacheTypeNone, YES, url); 286 + completedBlock(nil, nil, nil, SDImageCacheTypeNone, YES, url);
292 } 287 }
293 }); 288 });
294 @synchronized (self.runningOperations) { 289 @synchronized (self.runningOperations) {
@@ -57,7 +57,7 @@ @@ -57,7 +57,7 @@
57 - (void)startPrefetchingAtIndex:(NSUInteger)index { 57 - (void)startPrefetchingAtIndex:(NSUInteger)index {
58 if (index >= self.prefetchURLs.count) return; 58 if (index >= self.prefetchURLs.count) return;
59 self.requestedCount++; 59 self.requestedCount++;
60 - [self.manager loadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 60 + [self.manager loadImageWithURL:self.prefetchURLs[index] options:self.options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
61 if (!finished) return; 61 if (!finished) return;
62 self.finishedCount++; 62 self.finishedCount++;
63 63
@@ -81,7 +81,7 @@ @@ -81,7 +81,7 @@
81 */ 81 */
82 - (void)sd_setImageWithURL:(nullable NSURL *)url 82 - (void)sd_setImageWithURL:(nullable NSURL *)url
83 forState:(UIControlState)state 83 forState:(UIControlState)state
84 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 84 + completed:(nullable SDExternalCompletionBlock)completedBlock;
85 85
86 /** 86 /**
87 * Set the imageView `image` with an `url`, placeholder. 87 * Set the imageView `image` with an `url`, placeholder.
@@ -100,7 +100,7 @@ @@ -100,7 +100,7 @@
100 - (void)sd_setImageWithURL:(nullable NSURL *)url 100 - (void)sd_setImageWithURL:(nullable NSURL *)url
101 forState:(UIControlState)state 101 forState:(UIControlState)state
102 placeholderImage:(nullable UIImage *)placeholder 102 placeholderImage:(nullable UIImage *)placeholder
103 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 103 + completed:(nullable SDExternalCompletionBlock)completedBlock;
104 104
105 /** 105 /**
106 * Set the imageView `image` with an `url`, placeholder and custom options. 106 * Set the imageView `image` with an `url`, placeholder and custom options.
@@ -121,7 +121,7 @@ @@ -121,7 +121,7 @@
121 forState:(UIControlState)state 121 forState:(UIControlState)state
122 placeholderImage:(nullable UIImage *)placeholder 122 placeholderImage:(nullable UIImage *)placeholder
123 options:(SDWebImageOptions)options 123 options:(SDWebImageOptions)options
124 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 124 + completed:(nullable SDExternalCompletionBlock)completedBlock;
125 125
126 /** 126 /**
127 * Set the backgroundImageView `image` with an `url`. 127 * Set the backgroundImageView `image` with an `url`.
@@ -178,7 +178,7 @@ @@ -178,7 +178,7 @@
178 */ 178 */
179 - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url 179 - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
180 forState:(UIControlState)state 180 forState:(UIControlState)state
181 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 181 + completed:(nullable SDExternalCompletionBlock)completedBlock;
182 182
183 /** 183 /**
184 * Set the backgroundImageView `image` with an `url`, placeholder. 184 * Set the backgroundImageView `image` with an `url`, placeholder.
@@ -197,7 +197,7 @@ @@ -197,7 +197,7 @@
197 - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url 197 - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
198 forState:(UIControlState)state 198 forState:(UIControlState)state
199 placeholderImage:(nullable UIImage *)placeholder 199 placeholderImage:(nullable UIImage *)placeholder
200 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 200 + completed:(nullable SDExternalCompletionBlock)completedBlock;
201 201
202 /** 202 /**
203 * Set the backgroundImageView `image` with an `url`, placeholder and custom options. 203 * Set the backgroundImageView `image` with an `url`, placeholder and custom options.
@@ -217,7 +217,7 @@ @@ -217,7 +217,7 @@
217 forState:(UIControlState)state 217 forState:(UIControlState)state
218 placeholderImage:(nullable UIImage *)placeholder 218 placeholderImage:(nullable UIImage *)placeholder
219 options:(SDWebImageOptions)options 219 options:(SDWebImageOptions)options
220 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 220 + completed:(nullable SDExternalCompletionBlock)completedBlock;
221 221
222 /** 222 /**
223 * Cancel the current image download 223 * Cancel the current image download
@@ -42,11 +42,11 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary; @@ -42,11 +42,11 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
42 [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; 42 [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
43 } 43 }
44 44
45 -- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDWebImageCompletionBlock)completedBlock { 45 +- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
46 [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock]; 46 [self sd_setImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
47 } 47 }
48 48
49 -- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock { 49 +- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
50 [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock]; 50 [self sd_setImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
51 } 51 }
52 52
@@ -54,8 +54,7 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary; @@ -54,8 +54,7 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
54 forState:(UIControlState)state 54 forState:(UIControlState)state
55 placeholderImage:(nullable UIImage *)placeholder 55 placeholderImage:(nullable UIImage *)placeholder
56 options:(SDWebImageOptions)options 56 options:(SDWebImageOptions)options
57 - completed:(nullable SDWebImageCompletionBlock)completedBlock {  
58 - 57 + completed:(nullable SDExternalCompletionBlock)completedBlock {
59 [self setImage:placeholder forState:state]; 58 [self setImage:placeholder forState:state];
60 [self sd_cancelImageLoadForState:state]; 59 [self sd_cancelImageLoadForState:state];
61 60
@@ -75,7 +74,7 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary; @@ -75,7 +74,7 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
75 self.imageURLStorage[@(state)] = url; 74 self.imageURLStorage[@(state)] = url;
76 75
77 __weak __typeof(self)wself = self; 76 __weak __typeof(self)wself = self;
78 - id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 77 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
79 if (!wself) return; 78 if (!wself) return;
80 dispatch_main_sync_safe(^{ 79 dispatch_main_sync_safe(^{
81 __strong UIButton *sself = wself; 80 __strong UIButton *sself = wself;
@@ -108,11 +107,11 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary; @@ -108,11 +107,11 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
108 [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil]; 107 [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:options completed:nil];
109 } 108 }
110 109
111 -- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDWebImageCompletionBlock)completedBlock { 110 +- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state completed:(nullable SDExternalCompletionBlock)completedBlock {
112 [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock]; 111 [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:nil options:0 completed:completedBlock];
113 } 112 }
114 113
115 -- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock { 114 +- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
116 [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock]; 115 [self sd_setBackgroundImageWithURL:url forState:state placeholderImage:placeholder options:0 completed:completedBlock];
117 } 116 }
118 117
@@ -120,14 +119,14 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary; @@ -120,14 +119,14 @@ typedef NSMutableDictionary<NSNumber *, NSURL *> SDStateImageURLDictionary;
120 forState:(UIControlState)state 119 forState:(UIControlState)state
121 placeholderImage:(nullable UIImage *)placeholder 120 placeholderImage:(nullable UIImage *)placeholder
122 options:(SDWebImageOptions)options 121 options:(SDWebImageOptions)options
123 - completed:(nullable SDWebImageCompletionBlock)completedBlock { 122 + completed:(nullable SDExternalCompletionBlock)completedBlock {
124 [self sd_cancelBackgroundImageLoadForState:state]; 123 [self sd_cancelBackgroundImageLoadForState:state];
125 124
126 [self setBackgroundImage:placeholder forState:state]; 125 [self setBackgroundImage:placeholder forState:state];
127 126
128 if (url) { 127 if (url) {
129 __weak __typeof(self)wself = self; 128 __weak __typeof(self)wself = self;
130 - id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 129 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
131 if (!wself) return; 130 if (!wself) return;
132 dispatch_main_sync_safe(^{ 131 dispatch_main_sync_safe(^{
133 __strong UIButton *sself = wself; 132 __strong UIButton *sself = wself;
@@ -11,10 +11,14 @@ @@ -11,10 +11,14 @@
11 11
12 @interface UIImage (GIF) 12 @interface UIImage (GIF)
13 13
14 -+ (UIImage *)sd_animatedGIFNamed:(NSString *)name;  
15 - 14 +/**
  15 + * Compatibility method - creates an animated UIImage from an NSData, it will only contain the 1st frame image
  16 + */
16 + (UIImage *)sd_animatedGIFWithData:(NSData *)data; 17 + (UIImage *)sd_animatedGIFWithData:(NSData *)data;
17 18
18 -- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size; 19 +/**
  20 + * Checks if an UIImage instance is a GIF. Will use the `images` array
  21 + */
  22 +- (BOOL)isGIF;
19 23
20 @end 24 @end
@@ -9,6 +9,7 @@ @@ -9,6 +9,7 @@
9 9
10 #import "UIImage+GIF.h" 10 #import "UIImage+GIF.h"
11 #import <ImageIO/ImageIO.h> 11 #import <ImageIO/ImageIO.h>
  12 +#import "objc/runtime.h"
12 13
13 @implementation UIImage (GIF) 14 @implementation UIImage (GIF)
14 15
@@ -21,142 +22,26 @@ @@ -21,142 +22,26 @@
21 22
22 size_t count = CGImageSourceGetCount(source); 23 size_t count = CGImageSourceGetCount(source);
23 24
24 - UIImage *animatedImage; 25 + UIImage *staticImage;
25 26
26 if (count <= 1) { 27 if (count <= 1) {
27 - animatedImage = [[UIImage alloc] initWithData:data];  
28 - }  
29 - else {  
30 - NSMutableArray *images = [NSMutableArray array];  
31 -  
32 - NSTimeInterval duration = 0.0f;  
33 -  
34 - for (size_t i = 0; i < count; i++) {  
35 - CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);  
36 - if (!image) {  
37 - continue;  
38 - }  
39 -  
40 - duration += [self sd_frameDurationAtIndex:i source:source];  
41 -  
42 - [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];  
43 -  
44 - CGImageRelease(image);  
45 - }  
46 -  
47 - if (!duration) {  
48 - duration = (1.0f / 10.0f) * count;  
49 - }  
50 -  
51 - animatedImage = [UIImage animatedImageWithImages:images duration:duration]; 28 + staticImage = [[UIImage alloc] initWithData:data];
  29 + } else {
  30 + // we will only retrieve the 1st frame. the full GIF support is available via the FLAnimatedImageView category.
  31 + // this here is only code to allow drawing animated images as static ones
  32 + CGImageRef CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
  33 + UIImage *frameImage = [UIImage imageWithCGImage:CGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
  34 + staticImage = [UIImage animatedImageWithImages:@[frameImage] duration:0.0f];
  35 + CGImageRelease(CGImage);
52 } 36 }
53 37
54 CFRelease(source); 38 CFRelease(source);
55 39
56 - return animatedImage;  
57 -}  
58 -  
59 -+ (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source {  
60 - float frameDuration = 0.1f;  
61 - CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil);  
62 - NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties;  
63 - NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary];  
64 -  
65 - NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime];  
66 - if (delayTimeUnclampedProp) {  
67 - frameDuration = delayTimeUnclampedProp.floatValue;  
68 - }  
69 - else {  
70 -  
71 - NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime];  
72 - if (delayTimeProp) {  
73 - frameDuration = delayTimeProp.floatValue;  
74 - }  
75 - }  
76 -  
77 - // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.  
78 - // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify  
79 - // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>  
80 - // for more information.  
81 -  
82 - if (frameDuration < 0.011f) {  
83 - frameDuration = 0.100f;  
84 - }  
85 -  
86 - CFRelease(cfFrameProperties);  
87 - return frameDuration; 40 + return staticImage;
88 } 41 }
89 42
90 -+ (UIImage *)sd_animatedGIFNamed:(NSString *)name {  
91 - CGFloat scale = [UIScreen mainScreen].scale;  
92 -  
93 - if (scale > 1.0f) {  
94 - NSString *retinaPath = [[NSBundle mainBundle] pathForResource:[name stringByAppendingString:@"@2x"] ofType:@"gif"];  
95 -  
96 - NSData *data = [NSData dataWithContentsOfFile:retinaPath];  
97 -  
98 - if (data) {  
99 - return [UIImage sd_animatedGIFWithData:data];  
100 - }  
101 -  
102 - NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];  
103 -  
104 - data = [NSData dataWithContentsOfFile:path];  
105 -  
106 - if (data) {  
107 - return [UIImage sd_animatedGIFWithData:data];  
108 - }  
109 -  
110 - return [UIImage imageNamed:name];  
111 - }  
112 - else {  
113 - NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:@"gif"];  
114 -  
115 - NSData *data = [NSData dataWithContentsOfFile:path];  
116 -  
117 - if (data) {  
118 - return [UIImage sd_animatedGIFWithData:data];  
119 - }  
120 -  
121 - return [UIImage imageNamed:name];  
122 - }  
123 -}  
124 -  
125 -- (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size {  
126 - if (CGSizeEqualToSize(self.size, size) || CGSizeEqualToSize(size, CGSizeZero)) {  
127 - return self;  
128 - }  
129 -  
130 - CGSize scaledSize = size;  
131 - CGPoint thumbnailPoint = CGPointZero;  
132 -  
133 - CGFloat widthFactor = size.width / self.size.width;  
134 - CGFloat heightFactor = size.height / self.size.height;  
135 - CGFloat scaleFactor = (widthFactor > heightFactor) ? widthFactor : heightFactor;  
136 - scaledSize.width = self.size.width * scaleFactor;  
137 - scaledSize.height = self.size.height * scaleFactor;  
138 -  
139 - if (widthFactor > heightFactor) {  
140 - thumbnailPoint.y = (size.height - scaledSize.height) * 0.5;  
141 - }  
142 - else if (widthFactor < heightFactor) {  
143 - thumbnailPoint.x = (size.width - scaledSize.width) * 0.5;  
144 - }  
145 -  
146 - NSMutableArray *scaledImages = [NSMutableArray array];  
147 -  
148 - for (UIImage *image in self.images) {  
149 - UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);  
150 -  
151 - [image drawInRect:CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledSize.width, scaledSize.height)];  
152 - UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();  
153 -  
154 - [scaledImages addObject:newImage];  
155 -  
156 - UIGraphicsEndImageContext();  
157 - }  
158 -  
159 - return [UIImage animatedImageWithImages:scaledImages duration:self.duration]; 43 +- (BOOL)isGIF {
  44 + return (self.images != nil);
160 } 45 }
161 46
162 @end 47 @end
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 * The fourth parameter is the original image url. 48 * The fourth parameter is the original image url.
49 */ 49 */
50 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url 50 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
51 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 51 + completed:(nullable SDExternalCompletionBlock)completedBlock;
52 52
53 /** 53 /**
54 * Set the imageView `highlightedImage` with an `url` and custom options. 54 * Set the imageView `highlightedImage` with an `url` and custom options.
@@ -65,7 +65,7 @@ @@ -65,7 +65,7 @@
65 */ 65 */
66 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url 66 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
67 options:(SDWebImageOptions)options 67 options:(SDWebImageOptions)options
68 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 68 + completed:(nullable SDExternalCompletionBlock)completedBlock;
69 69
70 /** 70 /**
71 * Set the imageView `highlightedImage` with an `url` and custom options. 71 * Set the imageView `highlightedImage` with an `url` and custom options.
@@ -84,7 +84,7 @@ @@ -84,7 +84,7 @@
84 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url 84 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
85 options:(SDWebImageOptions)options 85 options:(SDWebImageOptions)options
86 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 86 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
87 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 87 + completed:(nullable SDExternalCompletionBlock)completedBlock;
88 88
89 /** 89 /**
90 * Cancel the current download 90 * Cancel the current download
@@ -21,40 +21,39 @@ @@ -21,40 +21,39 @@
21 [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil]; 21 [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:nil];
22 } 22 }
23 23
24 -- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url completed:(nullable SDWebImageCompletionBlock)completedBlock { 24 +- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
25 [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock]; 25 [self sd_setHighlightedImageWithURL:url options:0 progress:nil completed:completedBlock];
26 } 26 }
27 27
28 -- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url options:(SDWebImageOptions)options completed:(nullable SDWebImageCompletionBlock)completedBlock { 28 +- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
29 [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock]; 29 [self sd_setHighlightedImageWithURL:url options:options progress:nil completed:completedBlock];
30 } 30 }
31 31
32 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url 32 - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
33 options:(SDWebImageOptions)options 33 options:(SDWebImageOptions)options
34 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 34 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
35 - completed:(nullable SDWebImageCompletionBlock)completedBlock { 35 + completed:(nullable SDExternalCompletionBlock)completedBlock {
36 [self sd_cancelCurrentHighlightedImageLoad]; 36 [self sd_cancelCurrentHighlightedImageLoad];
37 37
38 if (url) { 38 if (url) {
39 __weak __typeof(self)wself = self; 39 __weak __typeof(self)wself = self;
40 - id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 40 + id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
41 if (!wself) return; 41 if (!wself) return;
42 - dispatch_main_sync_safe (^  
43 - {  
44 - if (!wself) return;  
45 - if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)  
46 - {  
47 - completedBlock(image, error, cacheType, url);  
48 - return;  
49 - }  
50 - else if (image) {  
51 - wself.highlightedImage = image;  
52 - [wself setNeedsLayout];  
53 - }  
54 - if (completedBlock && finished) {  
55 - completedBlock(image, error, cacheType, url);  
56 - }  
57 - }); 42 + dispatch_main_sync_safe (^{
  43 + if (!wself) return;
  44 + if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
  45 + {
  46 + completedBlock(image, error, cacheType, url);
  47 + return;
  48 + }
  49 + else if (image) {
  50 + wself.highlightedImage = image;
  51 + [wself setNeedsLayout];
  52 + }
  53 + if (completedBlock && finished) {
  54 + completedBlock(image, error, cacheType, url);
  55 + }
  56 + });
58 }]; 57 }];
59 [self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey]; 58 [self sd_setImageLoadOperation:operation forKey:UIImageViewHighlightedWebCacheOperationKey];
60 } else { 59 } else {
@@ -48,7 +48,7 @@ @@ -48,7 +48,7 @@
48 * Get the current image URL. 48 * Get the current image URL.
49 * 49 *
50 * Note that because of the limitations of categories this property can get out of sync 50 * Note that because of the limitations of categories this property can get out of sync
51 - * if you use sd_setImage: directly. 51 + * if you use setImage: directly.
52 */ 52 */
53 - (nullable NSURL *)sd_imageURL; 53 - (nullable NSURL *)sd_imageURL;
54 54
@@ -99,7 +99,7 @@ @@ -99,7 +99,7 @@
99 * The fourth parameter is the original image url. 99 * The fourth parameter is the original image url.
100 */ 100 */
101 - (void)sd_setImageWithURL:(nullable NSURL *)url 101 - (void)sd_setImageWithURL:(nullable NSURL *)url
102 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 102 + completed:(nullable SDExternalCompletionBlock)completedBlock;
103 103
104 /** 104 /**
105 * Set the imageView `image` with an `url`, placeholder. 105 * Set the imageView `image` with an `url`, placeholder.
@@ -116,7 +116,7 @@ @@ -116,7 +116,7 @@
116 */ 116 */
117 - (void)sd_setImageWithURL:(nullable NSURL *)url 117 - (void)sd_setImageWithURL:(nullable NSURL *)url
118 placeholderImage:(nullable UIImage *)placeholder 118 placeholderImage:(nullable UIImage *)placeholder
119 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 119 + completed:(nullable SDExternalCompletionBlock)completedBlock;
120 120
121 /** 121 /**
122 * Set the imageView `image` with an `url`, placeholder and custom options. 122 * Set the imageView `image` with an `url`, placeholder and custom options.
@@ -135,7 +135,7 @@ @@ -135,7 +135,7 @@
135 - (void)sd_setImageWithURL:(nullable NSURL *)url 135 - (void)sd_setImageWithURL:(nullable NSURL *)url
136 placeholderImage:(nullable UIImage *)placeholder 136 placeholderImage:(nullable UIImage *)placeholder
137 options:(SDWebImageOptions)options 137 options:(SDWebImageOptions)options
138 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 138 + completed:(nullable SDExternalCompletionBlock)completedBlock;
139 139
140 /** 140 /**
141 * Set the imageView `image` with an `url`, placeholder and custom options. 141 * Set the imageView `image` with an `url`, placeholder and custom options.
@@ -156,7 +156,7 @@ @@ -156,7 +156,7 @@
156 placeholderImage:(nullable UIImage *)placeholder 156 placeholderImage:(nullable UIImage *)placeholder
157 options:(SDWebImageOptions)options 157 options:(SDWebImageOptions)options
158 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 158 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
159 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 159 + completed:(nullable SDExternalCompletionBlock)completedBlock;
160 160
161 /** 161 /**
162 * Set the imageView `image` with an `url` and optionally a placeholder image. 162 * Set the imageView `image` with an `url` and optionally a placeholder image.
@@ -177,7 +177,7 @@ @@ -177,7 +177,7 @@
177 placeholderImage:(nullable UIImage *)placeholder 177 placeholderImage:(nullable UIImage *)placeholder
178 options:(SDWebImageOptions)options 178 options:(SDWebImageOptions)options
179 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 179 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
180 - completed:(nullable SDWebImageCompletionBlock)completedBlock; 180 + completed:(nullable SDExternalCompletionBlock)completedBlock;
181 181
182 /** 182 /**
183 * Download an array of images and starts them in an animation loop 183 * Download an array of images and starts them in an animation loop
@@ -205,4 +205,9 @@ @@ -205,4 +205,9 @@
205 */ 205 */
206 - (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style; 206 - (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
207 207
  208 +- (BOOL)showActivityIndicatorView;
  209 +- (void)addActivityIndicator;
  210 +- (void)removeActivityIndicator;
  211 +
  212 +
208 @end 213 @end
@@ -29,15 +29,15 @@ static char TAG_ACTIVITY_SHOW; @@ -29,15 +29,15 @@ static char TAG_ACTIVITY_SHOW;
29 [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil]; 29 [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
30 } 30 }
31 31
32 -- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDWebImageCompletionBlock)completedBlock { 32 +- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
33 [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock]; 33 [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
34 } 34 }
35 35
36 -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDWebImageCompletionBlock)completedBlock { 36 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
37 [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock]; 37 [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
38 } 38 }
39 39
40 -- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDWebImageCompletionBlock)completedBlock { 40 +- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
41 [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock]; 41 [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
42 } 42 }
43 43
@@ -45,7 +45,7 @@ static char TAG_ACTIVITY_SHOW; @@ -45,7 +45,7 @@ static char TAG_ACTIVITY_SHOW;
45 placeholderImage:(nullable UIImage *)placeholder 45 placeholderImage:(nullable UIImage *)placeholder
46 options:(SDWebImageOptions)options 46 options:(SDWebImageOptions)options
47 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 47 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
48 - completed:(nullable SDWebImageCompletionBlock)completedBlock { 48 + completed:(nullable SDExternalCompletionBlock)completedBlock {
49 [self sd_cancelCurrentImageLoad]; 49 [self sd_cancelCurrentImageLoad];
50 objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 50 objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
51 51
@@ -63,7 +63,7 @@ static char TAG_ACTIVITY_SHOW; @@ -63,7 +63,7 @@ static char TAG_ACTIVITY_SHOW;
63 } 63 }
64 64
65 __weak __typeof(self)wself = self; 65 __weak __typeof(self)wself = self;
66 - id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 66 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
67 [wself removeActivityIndicator]; 67 [wself removeActivityIndicator];
68 if (!wself) return; 68 if (!wself) return;
69 dispatch_main_sync_safe(^{ 69 dispatch_main_sync_safe(^{
@@ -103,7 +103,7 @@ static char TAG_ACTIVITY_SHOW; @@ -103,7 +103,7 @@ static char TAG_ACTIVITY_SHOW;
103 placeholderImage:(nullable UIImage *)placeholder 103 placeholderImage:(nullable UIImage *)placeholder
104 options:(SDWebImageOptions)options 104 options:(SDWebImageOptions)options
105 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock 105 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
106 - completed:(nullable SDWebImageCompletionBlock)completedBlock { 106 + completed:(nullable SDExternalCompletionBlock)completedBlock {
107 NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url]; 107 NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
108 UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key]; 108 UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key];
109 109
@@ -121,7 +121,7 @@ static char TAG_ACTIVITY_SHOW; @@ -121,7 +121,7 @@ static char TAG_ACTIVITY_SHOW;
121 NSMutableArray<id<SDWebImageOperation>> *operationsArray = [[NSMutableArray alloc] init]; 121 NSMutableArray<id<SDWebImageOperation>> *operationsArray = [[NSMutableArray alloc] init];
122 122
123 for (NSURL *logoImageURL in arrayOfURLs) { 123 for (NSURL *logoImageURL in arrayOfURLs) {
124 - id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 124 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
125 if (!wself) return; 125 if (!wself) return;
126 dispatch_main_sync_safe(^{ 126 dispatch_main_sync_safe(^{
127 __strong UIImageView *sself = wself; 127 __strong UIImageView *sself = wself;
@@ -163,11 +163,11 @@ static char TAG_ACTIVITY_SHOW; @@ -163,11 +163,11 @@ static char TAG_ACTIVITY_SHOW;
163 objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN); 163 objc_setAssociatedObject(self, &TAG_ACTIVITY_INDICATOR, activityIndicator, OBJC_ASSOCIATION_RETAIN);
164 } 164 }
165 165
166 -- (void)setShowActivityIndicatorView:(BOOL)show{ 166 +- (void)setShowActivityIndicatorView:(BOOL)show {
167 objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, @(show), OBJC_ASSOCIATION_RETAIN); 167 objc_setAssociatedObject(self, &TAG_ACTIVITY_SHOW, @(show), OBJC_ASSOCIATION_RETAIN);
168 } 168 }
169 169
170 -- (BOOL)showActivityIndicatorView{ 170 +- (BOOL)showActivityIndicatorView {
171 return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue]; 171 return [objc_getAssociatedObject(self, &TAG_ACTIVITY_SHOW) boolValue];
172 } 172 }
173 173
@@ -100,7 +100,7 @@ NSString *kImageTestKey = @"TestImageKey.jpg"; @@ -100,7 +100,7 @@ NSString *kImageTestKey = @"TestImageKey.jpg";
100 //- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock; 100 //- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;
101 UIImage *imageForTesting = [self imageForTesting]; 101 UIImage *imageForTesting = [self imageForTesting];
102 [self.sharedImageCache storeImage:imageForTesting forKey:kImageTestKey]; 102 [self.sharedImageCache storeImage:imageForTesting forKey:kImageTestKey];
103 - NSOperation *operation = [self.sharedImageCache queryDiskCacheForKey:kImageTestKey done:^(UIImage *image, SDImageCacheType cacheType) { 103 + NSOperation *operation = [self.sharedImageCache queryDiskCacheForKey:kImageTestKey done:^(UIImage *image, NSData *data, SDImageCacheType cacheType) {
104 expect(image).to.equal(imageForTesting); 104 expect(image).to.equal(imageForTesting);
105 }]; 105 }];
106 expect(operation).toNot.beNil; 106 expect(operation).toNot.beNil;
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 - (void)testThatDownloadingSameURLTwiceAndCancellingFirstWorks { 36 - (void)testThatDownloadingSameURLTwiceAndCancellingFirstWorks {
37 XCTestExpectation *expectation = [self expectationWithDescription:@"Correct image downloads"]; 37 XCTestExpectation *expectation = [self expectationWithDescription:@"Correct image downloads"];
38 38
39 - NSURL *imageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.jpg?20120509154705"]; 39 + NSURL *imageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage000.jpg"];
40 40
41 id token1 = [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL 41 id token1 = [[SDWebImageDownloader sharedDownloader] downloadImageWithURL:imageURL
42 options:0 42 options:0
@@ -40,7 +40,10 @@ static int64_t kAsyncTestTimeout = 5; @@ -40,7 +40,10 @@ static int64_t kAsyncTestTimeout = 5;
40 40
41 NSURL *originalImageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage000.jpg"]; 41 NSURL *originalImageURL = [NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage000.jpg"];
42 42
43 - [[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 43 + [[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL
  44 + options:SDWebImageRefreshCached
  45 + progress:nil
  46 + completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
44 expect(image).toNot.beNil(); 47 expect(image).toNot.beNil();
45 expect(error).to.beNil(); 48 expect(error).to.beNil();
46 expect(originalImageURL).to.equal(imageURL); 49 expect(originalImageURL).to.equal(imageURL);
@@ -57,7 +60,10 @@ static int64_t kAsyncTestTimeout = 5; @@ -57,7 +60,10 @@ static int64_t kAsyncTestTimeout = 5;
57 60
58 NSURL *originalImageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.png"]; 61 NSURL *originalImageURL = [NSURL URLWithString:@"http://static2.dmcdn.net/static/video/656/177/44771656:jpeg_preview_small.png"];
59 62
60 - [[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL options:SDWebImageRefreshCached progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { 63 + [[SDWebImageManager sharedManager] loadImageWithURL:originalImageURL
  64 + options:SDWebImageRefreshCached
  65 + progress:nil
  66 + completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
61 expect(image).to.beNil(); 67 expect(image).to.beNil();
62 expect(error).toNot.beNil(); 68 expect(error).toNot.beNil();
63 expect(originalImageURL).to.equal(imageURL); 69 expect(originalImageURL).to.equal(imageURL);
FLAnimatedImage @ 25307796
  1 +Subproject commit 25307796cfcf66cb5b98774e050e93f64e0f2cde