Merge branch 'master' of https://github.com/rs/SDWebImage into 5.x
* 'master' of https://github.com/rs/SDWebImage: Update the comments and a little enhancement for FLAnimatedImageView Category Use a dispatch semaphore to keep thread safe for downloader because it need the hold cancel and add procedure be thread-safe Add the current image/alternateImage url for NSButton category. A little code refactoring Update macOS demo to add a clear cache button using NSButton category Fix that reset alternateImage cancel the image load operation for NSButton+WebCache Add WebCache category for NSButton on macOS A little enhancement to avoid block capture the heap object Use a internal method to avoid thread-safe issue for file manager. Remove that checkIOQueue and add sync version exist API Add the image transition argument for all UIView+WebCache, make this easy for user to do some fade transition. It also reuse the current setImageBlock and make it easy to customize # Conflicts: # SDWebImage.xcodeproj/project.pbxproj # SDWebImage/SDImageCache.h # SDWebImage/SDImageCache.m # SDWebImage/UIView+WebCache.h # SDWebImage/UIView+WebCache.m # WebImage/SDWebImage.h
This commit is contained in:
commit
f05a1bf96f
|
@ -117,6 +117,7 @@
|
|||
MyCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
|
||||
if (cell == nil) {
|
||||
cell = [[MyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
|
||||
cell.customImageView.sd_imageTransition = SDWebImageTransition.fadeTransition;
|
||||
}
|
||||
|
||||
[cell.customImageView sd_setShowActivityIndicatorView:YES];
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Application-->
|
||||
|
@ -656,6 +657,9 @@
|
|||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="196" y="240" width="480" height="400"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="B8D-0N-5wS" id="1ov-0o-Na3"/>
|
||||
</connections>
|
||||
</window>
|
||||
<connections>
|
||||
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
|
||||
|
@ -675,23 +679,36 @@
|
|||
<subviews>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nbD-Cx-g7b">
|
||||
<rect key="frame" x="20" y="252" width="204" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="vAn-1d-apO"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kv0-67-hkh">
|
||||
<rect key="frame" x="256" y="252" width="204" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="f0P-c9-GMe"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JIp-Or-vBM">
|
||||
<rect key="frame" x="20" y="116" width="204" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="NJq-m3-LlB"/>
|
||||
</imageView>
|
||||
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="khI-tY-l0M">
|
||||
<rect key="frame" x="256" y="116" width="204" height="128"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" id="WbV-Do-9qy"/>
|
||||
</imageView>
|
||||
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="NqE-Zi-qhY">
|
||||
<rect key="frame" x="212" y="17" width="56" height="31"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="bevel" title="Clear" bezelStyle="regularSquare" alignment="center" borderStyle="border" imageScaling="proportionallyUpOrDown" inset="2" id="OYN-fG-Plb">
|
||||
<behavior key="behavior" pushIn="YES" changeContents="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="clearCacheButton" destination="NqE-Zi-qhY" id="eoz-cU-wWs"/>
|
||||
<outlet property="imageView1" destination="nbD-Cx-g7b" id="t2R-8w-ybH"/>
|
||||
<outlet property="imageView2" destination="kv0-67-hkh" id="i4k-5c-bno"/>
|
||||
<outlet property="imageView3" destination="JIp-Or-vBM" id="Qcf-og-59T"/>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
@property (weak) IBOutlet NSImageView *imageView2;
|
||||
@property (weak) IBOutlet NSImageView *imageView3;
|
||||
@property (weak) IBOutlet NSImageView *imageView4;
|
||||
@property (weak) IBOutlet NSButton *clearCacheButton;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -33,7 +34,23 @@
|
|||
[self.imageView1 sd_setImageWithURL:[NSURL URLWithString:@"http://assets.sbnation.com/assets/2512203/dogflops.gif"]];
|
||||
[self.imageView2 sd_setImageWithURL:[NSURL URLWithString:@"http://www.ioncannon.net/wp-content/uploads/2011/06/test2.webp"]];
|
||||
[self.imageView3 sd_setImageWithURL:[NSURL URLWithString:@"http://littlesvr.ca/apng/images/SteamEngine.webp"]];
|
||||
[self.imageView4 sd_setImageWithURL:[NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage001.jpg"]];
|
||||
self.imageView4.wantsLayer = YES;
|
||||
self.imageView4.sd_imageTransition = SDWebImageTransition.fadeTransition;
|
||||
[self.imageView4 sd_setImageWithURL:[NSURL URLWithString:@"http://s3.amazonaws.com/fast-image-cache/demo-images/FICDDemoImage001.jpg"] placeholderImage:nil options:SDWebImageForceTransition];
|
||||
|
||||
self.clearCacheButton.target = self;
|
||||
self.clearCacheButton.action = @selector(clearCacheButtonClicked:);
|
||||
[self.clearCacheButton sd_setImageWithURL:[NSURL URLWithString:@"https://png.icons8.com/color/100/000000/delete-sign.png"]];
|
||||
[self.clearCacheButton sd_setAlternateImageWithURL:[NSURL URLWithString:@"https://png.icons8.com/color/100/000000/checkmark.png"]];
|
||||
}
|
||||
|
||||
- (void)clearCacheButtonClicked:(NSResponder *)sender {
|
||||
NSButton *button = (NSButton *)sender;
|
||||
button.state = NSControlStateValueOn;
|
||||
[[SDImageCache sharedImageCache] clearMemory];
|
||||
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
|
||||
button.state = NSControlStateValueOff;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)setRepresentedObject:(id)representedObject {
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
00733A711BC4880E00A5A117 /* UIImageView+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 53922D95148C56230056699D /* UIImageView+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00733A721BC4880E00A5A117 /* UIView+WebCacheOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AB615301192DA24600A2D8E9 /* UIView+WebCacheOperation.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00733A731BC4880E00A5A117 /* SDWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 4A2CAE031AB4BB5400B6BC39 /* SDWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
321DB3612011D4D70015D2CB /* NSButton+WebCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 321DB35F2011D4D60015D2CB /* NSButton+WebCache.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
321DB3622011D4D70015D2CB /* NSButton+WebCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 321DB3602011D4D60015D2CB /* NSButton+WebCache.m */; };
|
||||
321E60861F38E8C800405457 /* SDWebImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 321E60841F38E8C800405457 /* SDWebImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
321E60871F38E8C800405457 /* SDWebImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 321E60841F38E8C800405457 /* SDWebImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
321E60881F38E8C800405457 /* SDWebImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 321E60841F38E8C800405457 /* SDWebImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -324,6 +326,18 @@
|
|||
324DF4BD200A14DC008A84CC /* SDWebImageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 324DF4B3200A14DC008A84CC /* SDWebImageDefine.m */; };
|
||||
324DF4BE200A14DC008A84CC /* SDWebImageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 324DF4B3200A14DC008A84CC /* SDWebImageDefine.m */; };
|
||||
324DF4BF200A14DC008A84CC /* SDWebImageDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 324DF4B3200A14DC008A84CC /* SDWebImageDefine.m */; };
|
||||
325312C8200F09910046BF1E /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 325312C6200F09910046BF1E /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
325312C9200F09910046BF1E /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 325312C6200F09910046BF1E /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
325312CA200F09910046BF1E /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 325312C6200F09910046BF1E /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
325312CB200F09910046BF1E /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 325312C6200F09910046BF1E /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
325312CC200F09910046BF1E /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 325312C6200F09910046BF1E /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
325312CD200F09910046BF1E /* SDWebImageTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 325312C6200F09910046BF1E /* SDWebImageTransition.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
325312CE200F09910046BF1E /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 325312C7200F09910046BF1E /* SDWebImageTransition.m */; };
|
||||
325312CF200F09910046BF1E /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 325312C7200F09910046BF1E /* SDWebImageTransition.m */; };
|
||||
325312D0200F09910046BF1E /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 325312C7200F09910046BF1E /* SDWebImageTransition.m */; };
|
||||
325312D1200F09910046BF1E /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 325312C7200F09910046BF1E /* SDWebImageTransition.m */; };
|
||||
325312D2200F09910046BF1E /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 325312C7200F09910046BF1E /* SDWebImageTransition.m */; };
|
||||
325312D3200F09910046BF1E /* SDWebImageTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 325312C7200F09910046BF1E /* SDWebImageTransition.m */; };
|
||||
3290FA041FA478AF0047D20C /* SDWebImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 3290FA021FA478AF0047D20C /* SDWebImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3290FA051FA478AF0047D20C /* SDWebImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 3290FA021FA478AF0047D20C /* SDWebImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3290FA061FA478AF0047D20C /* SDWebImageFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 3290FA021FA478AF0047D20C /* SDWebImageFrame.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
|
@ -1302,6 +1316,8 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
00733A4C1BC487C000A5A117 /* SDWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
321DB35F2011D4D60015D2CB /* NSButton+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSButton+WebCache.h"; path = "SDWebImage/NSButton+WebCache.h"; sourceTree = "<group>"; };
|
||||
321DB3602011D4D60015D2CB /* NSButton+WebCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSButton+WebCache.m"; path = "SDWebImage/NSButton+WebCache.m"; sourceTree = "<group>"; };
|
||||
321E60841F38E8C800405457 /* SDWebImageCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageCoder.h; sourceTree = "<group>"; };
|
||||
321E60851F38E8C800405457 /* SDWebImageCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImageCoder.m; sourceTree = "<group>"; };
|
||||
321E60921F38E8ED00405457 /* SDWebImageImageIOCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImageImageIOCoder.h; sourceTree = "<group>"; };
|
||||
|
@ -1349,6 +1365,8 @@
|
|||
323F8B3D1F38EF770092B609 /* muxread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = muxread.c; sourceTree = "<group>"; };
|
||||
324DF4B2200A14DC008A84CC /* SDWebImageDefine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageDefine.h; sourceTree = "<group>"; };
|
||||
324DF4B3200A14DC008A84CC /* SDWebImageDefine.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageDefine.m; sourceTree = "<group>"; };
|
||||
325312C6200F09910046BF1E /* SDWebImageTransition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTransition.h; sourceTree = "<group>"; };
|
||||
325312C7200F09910046BF1E /* SDWebImageTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTransition.m; sourceTree = "<group>"; };
|
||||
3290FA021FA478AF0047D20C /* SDWebImageFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageFrame.h; sourceTree = "<group>"; };
|
||||
3290FA031FA478AF0047D20C /* SDWebImageFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageFrame.m; sourceTree = "<group>"; };
|
||||
329A18571FFF5DFD008C9A2F /* UIImage+WebCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIImage+WebCache.h"; path = "SDWebImage/UIImage+WebCache.h"; sourceTree = "<group>"; };
|
||||
|
@ -1659,6 +1677,8 @@
|
|||
children = (
|
||||
329A18571FFF5DFD008C9A2F /* UIImage+WebCache.h */,
|
||||
329A18581FFF5DFD008C9A2F /* UIImage+WebCache.m */,
|
||||
321DB35F2011D4D60015D2CB /* NSButton+WebCache.h */,
|
||||
321DB3602011D4D60015D2CB /* NSButton+WebCache.m */,
|
||||
535699B415113E7300A4C397 /* MKAnnotationView+WebCache.h */,
|
||||
535699B515113E7300A4C397 /* MKAnnotationView+WebCache.m */,
|
||||
53922D93148C56230056699D /* UIButton+WebCache.h */,
|
||||
|
@ -1834,6 +1854,8 @@
|
|||
53922D92148C56230056699D /* SDWebImagePrefetcher.m */,
|
||||
324DF4B2200A14DC008A84CC /* SDWebImageDefine.h */,
|
||||
324DF4B3200A14DC008A84CC /* SDWebImageDefine.m */,
|
||||
325312C6200F09910046BF1E /* SDWebImageTransition.h */,
|
||||
325312C7200F09910046BF1E /* SDWebImageTransition.m */,
|
||||
);
|
||||
name = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2063,6 +2085,7 @@
|
|||
80377C481F2F666300F89830 /* bit_reader_utils.h in Headers */,
|
||||
80377C511F2F666300F89830 /* huffman_encode_utils.h in Headers */,
|
||||
00733A6B1BC4880E00A5A117 /* NSData+ImageContentType.h in Headers */,
|
||||
325312CB200F09910046BF1E /* SDWebImageTransition.h in Headers */,
|
||||
323F8C111F38EF770092B609 /* muxi.h in Headers */,
|
||||
80377EC41F2F66D500F89830 /* vp8li_dec.h in Headers */,
|
||||
00733A6A1BC4880E00A5A117 /* SDWebImagePrefetcher.h in Headers */,
|
||||
|
@ -2133,6 +2156,7 @@
|
|||
80377EA11F2F66D400F89830 /* vp8_dec.h in Headers */,
|
||||
80377C271F2F666300F89830 /* rescaler_utils.h in Headers */,
|
||||
323F8B511F38EF770092B609 /* backward_references_enc.h in Headers */,
|
||||
325312C9200F09910046BF1E /* SDWebImageTransition.h in Headers */,
|
||||
43A918651D8308FE00B3925F /* SDImageCacheConfig.h in Headers */,
|
||||
4314D1741D0E0E3B004B36C9 /* types.h in Headers */,
|
||||
4314D1761D0E0E3B004B36C9 /* decode.h in Headers */,
|
||||
|
@ -2211,6 +2235,7 @@
|
|||
431BB6E91D06D2C1006A3455 /* SDWebImageDownloaderOperation.h in Headers */,
|
||||
80377ED41F2F66D500F89830 /* vp8li_dec.h in Headers */,
|
||||
431BB6EB1D06D2C1006A3455 /* UIView+WebCacheOperation.h in Headers */,
|
||||
325312CC200F09910046BF1E /* SDWebImageTransition.h in Headers */,
|
||||
80377C6D1F2F666400F89830 /* huffman_utils.h in Headers */,
|
||||
80377C731F2F666400F89830 /* random_utils.h in Headers */,
|
||||
431BB6EE1D06D2C1006A3455 /* NSData+ImageContentType.h in Headers */,
|
||||
|
@ -2316,10 +2341,12 @@
|
|||
321E60C31F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
|
||||
80377E561F2F66A800F89830 /* lossless_common.h in Headers */,
|
||||
4397D2E91D0DDD8C00BB2784 /* UIImage+WebP.h in Headers */,
|
||||
325312CD200F09910046BF1E /* SDWebImageTransition.h in Headers */,
|
||||
4397D2EA1D0DDD8C00BB2784 /* UIImage+GIF.h in Headers */,
|
||||
321E60B51F38E90100405457 /* SDWebImageWebPCoder.h in Headers */,
|
||||
4397D2EB1D0DDD8C00BB2784 /* NSData+ImageContentType.h in Headers */,
|
||||
80377C851F2F666400F89830 /* huffman_encode_utils.h in Headers */,
|
||||
321DB3612011D4D70015D2CB /* NSButton+WebCache.h in Headers */,
|
||||
807A122D1F89636300EC2A9B /* SDWebImageCodersManager.h in Headers */,
|
||||
4397D2ED1D0DDD8C00BB2784 /* mux_types.h in Headers */,
|
||||
80377C831F2F666400F89830 /* filters_utils.h in Headers */,
|
||||
|
@ -2380,6 +2407,7 @@
|
|||
80377C2E1F2F666300F89830 /* bit_reader_utils.h in Headers */,
|
||||
80377C371F2F666300F89830 /* huffman_encode_utils.h in Headers */,
|
||||
4A2CAE2F1AB4BB7500B6BC39 /* UIImage+MultiFormat.h in Headers */,
|
||||
325312CA200F09910046BF1E /* SDWebImageTransition.h in Headers */,
|
||||
323F8C101F38EF770092B609 /* muxi.h in Headers */,
|
||||
80377EB41F2F66D400F89830 /* vp8li_dec.h in Headers */,
|
||||
4A2CAE1A1AB4BB6400B6BC39 /* SDWebImageOperation.h in Headers */,
|
||||
|
@ -2420,6 +2448,7 @@
|
|||
431738BF1CDFC2660008FEB9 /* encode.h in Headers */,
|
||||
53761316155AD0D5005750A4 /* SDImageCache.h in Headers */,
|
||||
323F8C0E1F38EF770092B609 /* muxi.h in Headers */,
|
||||
325312C8200F09910046BF1E /* SDWebImageTransition.h in Headers */,
|
||||
321E60A21F38E8F600405457 /* SDWebImageGIFCoder.h in Headers */,
|
||||
5D5B9142188EE8DD006D06BD /* NSData+ImageContentType.h in Headers */,
|
||||
80377BFE1F2F665300F89830 /* color_cache_utils.h in Headers */,
|
||||
|
@ -2772,6 +2801,7 @@
|
|||
323F8B991F38EF770092B609 /* near_lossless_enc.c in Sources */,
|
||||
80377DE81F2F66A700F89830 /* yuv_mips_dsp_r2.c in Sources */,
|
||||
80377EC31F2F66D500F89830 /* vp8l_dec.c in Sources */,
|
||||
325312D1200F09910046BF1E /* SDWebImageTransition.m in Sources */,
|
||||
321E609D1F38E8ED00405457 /* SDWebImageImageIOCoder.m in Sources */,
|
||||
323F8B9F1F38EF770092B609 /* picture_csp_enc.c in Sources */,
|
||||
43C892A31D9D6DDD0022038D /* demux.c in Sources */,
|
||||
|
@ -2936,6 +2966,7 @@
|
|||
323F8B451F38EF770092B609 /* analysis_enc.c in Sources */,
|
||||
80377C261F2F666300F89830 /* rescaler_utils.c in Sources */,
|
||||
323F8BBB1F38EF770092B609 /* predictor_enc.c in Sources */,
|
||||
325312CF200F09910046BF1E /* SDWebImageTransition.m in Sources */,
|
||||
80377D2F1F2F66A700F89830 /* dec_msa.c in Sources */,
|
||||
323F8C151F38EF770092B609 /* muxinternal.c in Sources */,
|
||||
80377D571F2F66A700F89830 /* rescaler_sse2.c in Sources */,
|
||||
|
@ -3082,6 +3113,7 @@
|
|||
80377C6A1F2F666400F89830 /* huffman_encode_utils.c in Sources */,
|
||||
323F8B481F38EF770092B609 /* analysis_enc.c in Sources */,
|
||||
80377DFE1F2F66A800F89830 /* dec_msa.c in Sources */,
|
||||
325312D2200F09910046BF1E /* SDWebImageTransition.m in Sources */,
|
||||
323F8BBE1F38EF770092B609 /* predictor_enc.c in Sources */,
|
||||
80377E261F2F66A800F89830 /* rescaler_sse2.c in Sources */,
|
||||
323F8C181F38EF770092B609 /* muxinternal.c in Sources */,
|
||||
|
@ -3233,6 +3265,7 @@
|
|||
80377C8C1F2F666400F89830 /* random_utils.c in Sources */,
|
||||
323F8BAD1F38EF770092B609 /* picture_psnr_enc.c in Sources */,
|
||||
323F8BC51F38EF770092B609 /* quant_enc.c in Sources */,
|
||||
321DB3622011D4D70015D2CB /* NSButton+WebCache.m in Sources */,
|
||||
80377C7F1F2F666400F89830 /* color_cache_utils.c in Sources */,
|
||||
80377E331F2F66A800F89830 /* alpha_processing_neon.c in Sources */,
|
||||
80377E401F2F66A800F89830 /* dec_clip_tables.c in Sources */,
|
||||
|
@ -3274,6 +3307,7 @@
|
|||
43A918701D8308FE00B3925F /* SDImageCacheConfig.m in Sources */,
|
||||
80377E4B1F2F66A800F89830 /* enc_mips32.c in Sources */,
|
||||
4397D2AB1D0DDD8C00BB2784 /* UIView+WebCacheOperation.m in Sources */,
|
||||
325312D3200F09910046BF1E /* SDWebImageTransition.m in Sources */,
|
||||
80377E391F2F66A800F89830 /* argb.c in Sources */,
|
||||
4369C2831D9807EC007E863A /* UIView+WebCache.m in Sources */,
|
||||
80377E611F2F66A800F89830 /* lossless_sse2.c in Sources */,
|
||||
|
@ -3361,6 +3395,7 @@
|
|||
323F8B981F38EF770092B609 /* near_lossless_enc.c in Sources */,
|
||||
80377D6F1F2F66A700F89830 /* cost.c in Sources */,
|
||||
80377EB31F2F66D400F89830 /* vp8l_dec.c in Sources */,
|
||||
325312D0200F09910046BF1E /* SDWebImageTransition.m in Sources */,
|
||||
321E609C1F38E8ED00405457 /* SDWebImageImageIOCoder.m in Sources */,
|
||||
323F8B9E1F38EF770092B609 /* picture_csp_enc.c in Sources */,
|
||||
80377D9E1F2F66A700F89830 /* upsampling_mips_dsp_r2.c in Sources */,
|
||||
|
@ -3511,6 +3546,7 @@
|
|||
80377CE51F2F66A100F89830 /* cost.c in Sources */,
|
||||
80377E931F2F66D000F89830 /* vp8l_dec.c in Sources */,
|
||||
321E609A1F38E8ED00405457 /* SDWebImageImageIOCoder.m in Sources */,
|
||||
325312CE200F09910046BF1E /* SDWebImageTransition.m in Sources */,
|
||||
323F8B9C1F38EF770092B609 /* picture_csp_enc.c in Sources */,
|
||||
80377D141F2F66A100F89830 /* upsampling_mips_dsp_r2.c in Sources */,
|
||||
80377D191F2F66A100F89830 /* yuv_mips_dsp_r2.c in Sources */,
|
||||
|
|
|
@ -72,23 +72,27 @@
|
|||
operationKey:nil
|
||||
setImageBlock:^(UIImage *image, NSData *imageData) {
|
||||
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:imageData];
|
||||
__block FLAnimatedImage *animatedImage = image.sd_FLAnimatedImage;
|
||||
// We could not directlly create the animated image on bacakground queue because it's time consuming, by the time we set it back, the current runloop has passed and the placeholder has been rendered and then replaced with animated image, this cause a flashing.
|
||||
// Previously we use a trick to firstly set the static poster image, then set animated image back to avoid flashing, but this trick fail when using with UIView transition because it's based on the Core Animation. Core Animation will capture the current layer state to do rendering, so even we later set it back, the transition will not update
|
||||
// Previously we use a trick to firstly set the static poster image, then set animated image back to avoid flashing, but this trick fail when using with UIView transition because it's based on the Core Animation. Core Animation will capture the current layer state to do rendering, so even we later set it back, the transition will not update. (it's recommended to use `SDWebImageTransition` instead)
|
||||
// So we have no choice to force store the FLAnimatedImage into memory cache using a associated object binding to UIImage instance. This consumed memory is adoptable and much smaller than `_UIAnimatedImage` for big GIF
|
||||
if (animatedImage || imageFormat == SDImageFormatGIF) {
|
||||
if (animatedImage) {
|
||||
weakSelf.animatedImage = animatedImage;
|
||||
FLAnimatedImage *associatedAnimatedImage = image.sd_FLAnimatedImage;
|
||||
if (associatedAnimatedImage || imageFormat == SDImageFormatGIF) {
|
||||
if (associatedAnimatedImage) {
|
||||
weakSelf.animatedImage = associatedAnimatedImage;
|
||||
weakSelf.image = nil;
|
||||
if (group) {
|
||||
dispatch_group_leave(group);
|
||||
}
|
||||
} else {
|
||||
// Firstly set the static poster image to avoid flashing
|
||||
UIImage *posterImage = image.images ? image.images.firstObject : image;
|
||||
weakSelf.image = posterImage;
|
||||
weakSelf.animatedImage = nil;
|
||||
// The imageData should not be nil, create FLAnimatedImage in global queue because it's time consuming, then set it back
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||
animatedImage = [FLAnimatedImage animatedImageWithGIFData:imageData];
|
||||
image.sd_FLAnimatedImage = animatedImage;
|
||||
FLAnimatedImage *animatedImage = [FLAnimatedImage animatedImageWithGIFData:imageData];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
image.sd_FLAnimatedImage = animatedImage;
|
||||
weakSelf.animatedImage = animatedImage;
|
||||
weakSelf.image = nil;
|
||||
if (group) {
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
#if SD_MAC
|
||||
|
||||
#import "SDWebImageManager.h"
|
||||
|
||||
@interface NSButton (WebCache)
|
||||
|
||||
#pragma mark - Image
|
||||
|
||||
/**
|
||||
* Get the current image URL.
|
||||
*/
|
||||
- (nullable NSURL *)sd_currentImageURL;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url`.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url` and a placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholder The image to be set initially, until the image request finishes.
|
||||
* @see sd_setImageWithURL:placeholderImage:options:
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url`, placeholder and custom options.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholder The image to be set initially, until the image request finishes.
|
||||
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url`.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url`, placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholder The image to be set initially, until the image request finishes.
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url`, placeholder and custom options.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholder The image to be set initially, until the image request finishes.
|
||||
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
/**
|
||||
* Set the button `image` with an `url`, placeholder and custom options.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the image.
|
||||
* @param placeholder The image to be set initially, until the image request finishes.
|
||||
* @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
|
||||
* @param progressBlock A block called while image is downloading
|
||||
* @note the progress block is executed on a background queue
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the image parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the image was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original image url.
|
||||
*/
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
#pragma mark - Alternate Image
|
||||
|
||||
/**
|
||||
* Get the current alternateImage URL.
|
||||
*/
|
||||
- (nullable NSURL *)sd_currentAlternateImageURL;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url`.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url` and a placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
* @param placeholder The alternateImage to be set initially, until the alternateImage request finishes.
|
||||
* @see sd_setAlternateImageWithURL:placeholderImage:options:
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url`, placeholder and custom options.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
* @param placeholder The alternateImage to be set initially, until the alternateImage request finishes.
|
||||
* @param options The options to use when downloading the alternateImage. @see SDWebImageOptions for the possible values.
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url`.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the alternateImage parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the alternateImage was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original alternateImage url.
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url`, placeholder.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
* @param placeholder The alternateImage to be set initially, until the alternateImage request finishes.
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the alternateImage parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the alternateImage was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original alternateImage url.
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url`, placeholder and custom options.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
* @param placeholder The alternateImage to be set initially, until the alternateImage request finishes.
|
||||
* @param options The options to use when downloading the alternateImage. @see SDWebImageOptions for the possible values.
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the alternateImage parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the alternateImage was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original alternateImage url.
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
/**
|
||||
* Set the button `alternateImage` with an `url`, placeholder and custom options.
|
||||
*
|
||||
* The download is asynchronous and cached.
|
||||
*
|
||||
* @param url The url for the alternateImage.
|
||||
* @param placeholder The alternateImage to be set initially, until the alternateImage request finishes.
|
||||
* @param options The options to use when downloading the alternateImage. @see SDWebImageOptions for the possible values.
|
||||
* @param progressBlock A block called while alternateImage is downloading
|
||||
* @note the progress block is executed on a background queue
|
||||
* @param completedBlock A block called when operation has been completed. This block has no return value
|
||||
* and takes the requested UIImage as first parameter. In case of error the alternateImage parameter
|
||||
* is nil and the second parameter may contain an NSError. The third parameter is a Boolean
|
||||
* indicating if the alternateImage was retrieved from the local cache or from the network.
|
||||
* The fourth parameter is the original alternateImage url.
|
||||
*/
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
#pragma mark - Cancel
|
||||
|
||||
/**
|
||||
* Cancel the current image download
|
||||
*/
|
||||
- (void)sd_cancelCurrentImageLoad;
|
||||
|
||||
/**
|
||||
* Cancel the current alternateImage download
|
||||
*/
|
||||
- (void)sd_cancelCurrentAlternateImageLoad;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "NSButton+WebCache.h"
|
||||
|
||||
#if SD_MAC
|
||||
|
||||
#import "objc/runtime.h"
|
||||
#import "UIView+WebCacheOperation.h"
|
||||
#import "UIView+WebCache.h"
|
||||
|
||||
static inline NSString * imageOperationKey() {
|
||||
return @"NSButtonImageOperation";
|
||||
}
|
||||
|
||||
static inline NSString * alternateImageOperationKey() {
|
||||
return @"NSButtonAlternateImageOperation";
|
||||
}
|
||||
|
||||
@implementation NSButton (WebCache)
|
||||
|
||||
#pragma mark - Image
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url {
|
||||
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
|
||||
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
|
||||
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
self.sd_currentImageURL = url;
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self sd_internalSetImageWithURL:url
|
||||
placeholderImage:placeholder
|
||||
options:options
|
||||
operationKey:imageOperationKey()
|
||||
setImageBlock:^(NSImage * _Nullable image, NSData * _Nullable imageData) {
|
||||
weakSelf.image = image;
|
||||
}
|
||||
progress:progressBlock
|
||||
completed:completedBlock];
|
||||
}
|
||||
|
||||
#pragma mark - Alternate Image
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url {
|
||||
[self sd_setAlternateImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
|
||||
[self sd_setAlternateImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
|
||||
[self sd_setAlternateImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
[self sd_setAlternateImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
|
||||
}
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
[self sd_setAlternateImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
|
||||
}
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
[self sd_setAlternateImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
|
||||
}
|
||||
|
||||
- (void)sd_setAlternateImageWithURL:(nullable NSURL *)url
|
||||
placeholderImage:(nullable UIImage *)placeholder
|
||||
options:(SDWebImageOptions)options
|
||||
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
self.sd_currentAlternateImageURL = url;
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self sd_internalSetImageWithURL:url
|
||||
placeholderImage:placeholder
|
||||
options:options
|
||||
operationKey:alternateImageOperationKey()
|
||||
setImageBlock:^(NSImage * _Nullable image, NSData * _Nullable imageData) {
|
||||
weakSelf.alternateImage = image;
|
||||
}
|
||||
progress:progressBlock
|
||||
completed:completedBlock];
|
||||
}
|
||||
|
||||
#pragma mark - Cancel
|
||||
|
||||
- (void)sd_cancelCurrentImageLoad {
|
||||
[self sd_cancelImageLoadOperationWithKey:imageOperationKey()];
|
||||
}
|
||||
|
||||
- (void)sd_cancelCurrentAlternateImageLoad {
|
||||
[self sd_cancelImageLoadOperationWithKey:alternateImageOperationKey()];
|
||||
}
|
||||
|
||||
#pragma mar - Private
|
||||
|
||||
- (NSURL *)sd_currentImageURL {
|
||||
return objc_getAssociatedObject(self, @selector(sd_currentImageURL));
|
||||
}
|
||||
|
||||
- (void)setSd_currentImageURL:(NSURL *)sd_currentImageURL {
|
||||
objc_setAssociatedObject(self, @selector(sd_currentImageURL), sd_currentImageURL, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
- (NSURL *)sd_currentAlternateImageURL {
|
||||
return objc_getAssociatedObject(self, @selector(sd_currentAlternateImageURL));
|
||||
}
|
||||
|
||||
- (void)setSd_currentAlternateImageURL:(NSURL *)sd_currentAlternateImageURL {
|
||||
objc_setAssociatedObject(self, @selector(sd_currentAlternateImageURL), sd_currentAlternateImageURL, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -207,7 +207,7 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
}
|
||||
data = [[SDWebImageCodersManager sharedInstance] encodedDataWithImage:image format:format];
|
||||
}
|
||||
[self safeStoreImageDataToDisk:data forKey:key error:&writeError];
|
||||
[self _storeImageDataToDisk:data forKey:key error:&writeError];
|
||||
}
|
||||
|
||||
if (completionBlock) {
|
||||
|
@ -236,16 +236,15 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
|
||||
__block BOOL success = YES;
|
||||
void(^storeImageDataBlock)(void) = ^{
|
||||
success = [self safeStoreImageDataToDisk:imageData forKey:key error:error];
|
||||
success = [self _storeImageDataToDisk:imageData forKey:key error:error];
|
||||
};
|
||||
dispatch_sync(self.ioQueue, storeImageDataBlock);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
- (BOOL)safeStoreImageDataToDisk:(nullable NSData *)imageData
|
||||
forKey:(nullable NSString *)key
|
||||
error:(NSError * _Nullable __autoreleasing * _Nonnull)error {
|
||||
// Make sure to call form io queue by caller
|
||||
- (BOOL)_storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key error:(NSError * _Nullable __autoreleasing * _Nonnull)error {
|
||||
if (!imageData || !key) {
|
||||
return NO;
|
||||
}
|
||||
|
@ -278,9 +277,8 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
#pragma mark - Query and Retrieve Ops
|
||||
|
||||
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock {
|
||||
dispatch_async(_ioQueue, ^{
|
||||
BOOL exists = [self diskImageDataExistsWithKey:key];
|
||||
|
||||
dispatch_async(self.ioQueue, ^{
|
||||
BOOL exists = [self _diskImageDataExistsWithKey:key];
|
||||
if (completionBlock) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
completionBlock(exists);
|
||||
|
@ -293,6 +291,20 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
|||
if (!key) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
__block BOOL exists = NO;
|
||||
dispatch_sync(self.ioQueue, ^{
|
||||
exists = [self _diskImageDataExistsWithKey:key];
|
||||
});
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
// Make sure to call form io queue by caller
|
||||
- (BOOL)_diskImageDataExistsWithKey:(nullable NSString *)key {
|
||||
if (!key) {
|
||||
return NO;
|
||||
}
|
||||
BOOL exists = [_fileManager fileExistsAtPath:[self defaultCachePathForKey:key]];
|
||||
|
||||
// fallback because of https://github.com/rs/SDWebImage/pull/976 that added the extension to the disk file name
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#import "SDWebImageDownloader.h"
|
||||
#import "SDWebImageDownloaderOperation.h"
|
||||
|
||||
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
|
||||
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
|
||||
|
||||
@interface SDWebImageDownloadToken ()
|
||||
|
||||
@property (nonatomic, weak, nullable) NSOperation<SDWebImageDownloaderOperationInterface> *downloadOperation;
|
||||
|
@ -36,6 +39,7 @@
|
|||
@property (assign, nonatomic, nullable) Class operationClass;
|
||||
@property (strong, nonatomic, nonnull) NSMutableDictionary<NSURL *, SDWebImageDownloaderOperation *> *URLOperations;
|
||||
@property (strong, nonatomic, nullable) SDHTTPHeadersMutableDictionary *HTTPHeaders;
|
||||
@property (strong, nonatomic, nonnull) dispatch_semaphore_t operationsLock; // a lock to keep the access to `URLOperations` thread-safe
|
||||
|
||||
// The session in which data tasks will run
|
||||
@property (strong, nonatomic) NSURLSession *session;
|
||||
|
@ -94,6 +98,7 @@
|
|||
#else
|
||||
_HTTPHeaders = [@{@"Accept": @"image/*;q=0.8"} mutableCopy];
|
||||
#endif
|
||||
_operationsLock = dispatch_semaphore_create(1);
|
||||
_downloadTimeout = 15.0;
|
||||
|
||||
[self createNewSessionWithConfiguration:sessionConfiguration];
|
||||
|
@ -238,11 +243,15 @@
|
|||
if (!url) {
|
||||
return;
|
||||
}
|
||||
SDWebImageDownloaderOperation *operation = [self operationForURL:url];
|
||||
BOOL canceled = [operation cancel:token.downloadOperationCancelToken];
|
||||
if (canceled) {
|
||||
[self removeOperationForURL:url];
|
||||
LOCK(self.operationsLock);
|
||||
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
|
||||
if (operation) {
|
||||
BOOL canceled = [operation cancel:token.downloadOperationCancelToken];
|
||||
if (canceled) {
|
||||
[self.URLOperations removeObjectForKey:url];
|
||||
}
|
||||
}
|
||||
UNLOCK(self.operationsLock);
|
||||
}
|
||||
|
||||
- (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
|
||||
|
@ -257,17 +266,24 @@
|
|||
return nil;
|
||||
}
|
||||
|
||||
SDWebImageDownloaderOperation *operation = [self operationForURL:url];
|
||||
LOCK(self.operationsLock);
|
||||
SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url];
|
||||
if (!operation) {
|
||||
operation = createCallback();
|
||||
[self setOperation:operation forURL:url];
|
||||
|
||||
__weak typeof(self) wself = self;
|
||||
operation.completionBlock = ^{
|
||||
__strong typeof(wself) sself = wself;
|
||||
[sself removeOperationForURL:url];
|
||||
if (!sself) {
|
||||
return;
|
||||
}
|
||||
LOCK(sself.operationsLock);
|
||||
[sself.URLOperations removeObjectForKey:url];
|
||||
UNLOCK(sself.operationsLock);
|
||||
};
|
||||
[self.URLOperations setObject:operation forKey:url];
|
||||
}
|
||||
UNLOCK(self.operationsLock);
|
||||
|
||||
id downloadOperationCancelToken = [operation addHandlersForProgress:progressBlock completed:completedBlock];
|
||||
|
||||
SDWebImageDownloadToken *token = [SDWebImageDownloadToken new];
|
||||
|
@ -288,35 +304,6 @@
|
|||
|
||||
#pragma mark Helper methods
|
||||
|
||||
- (SDWebImageDownloaderOperation *)operationForURL:(NSURL *)url {
|
||||
if (!url) {
|
||||
return nil;
|
||||
}
|
||||
SDWebImageDownloaderOperation *operation;
|
||||
@synchronized (self.URLOperations) {
|
||||
operation = [self.URLOperations objectForKey:url];
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
- (void)setOperation:(SDWebImageDownloaderOperation *)operation forURL:(NSURL *)url {
|
||||
if (!operation || !url) {
|
||||
return;
|
||||
}
|
||||
@synchronized (self.URLOperations) {
|
||||
[self.URLOperations setObject:operation forKey:url];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeOperationForURL:(NSURL *)url {
|
||||
if (!url) {
|
||||
return;
|
||||
}
|
||||
@synchronized (self.URLOperations) {
|
||||
[self.URLOperations removeObjectForKey:url];
|
||||
}
|
||||
}
|
||||
|
||||
- (SDWebImageDownloaderOperation *)operationWithTask:(NSURLSessionTask *)task {
|
||||
SDWebImageDownloaderOperation *returnOperation = nil;
|
||||
for (SDWebImageDownloaderOperation *operation in self.downloadQueue.operations) {
|
||||
|
|
|
@ -111,7 +111,11 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
|
|||
/**
|
||||
* By default, when the cache missed, the image is download from the network. This flag can prevent network to load from cache only.
|
||||
*/
|
||||
SDWebImageFromCacheOnly = 1 << 15
|
||||
SDWebImageFromCacheOnly = 1 << 15,
|
||||
/**
|
||||
* By default, when you use `SDWebImageTransition` to do some view transition after the image load finished, this transition is only applied for image download from the network. This mask can force to apply view transition for memory and disk cache as well.
|
||||
*/
|
||||
SDWebImageForceTransition = 1 << 16
|
||||
};
|
||||
|
||||
typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageCompat.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
#import "SDImageCache.h"
|
||||
|
||||
// for UIKit(iOS & tvOS), we use `+[UIView transitionWithView:duration:options:animations:completion]` for transition animations.
|
||||
// for AppKit(macOS), we use `+[NSAnimationContext runAnimationGroup:completionHandler:]` for transition animations. You can call `+[NSAnimationContext currentContext]` to grab the context during animations block.
|
||||
// These transition are provided for basic usage. If you need complicated animation, consider to directly use Core Animation or use `SDWebImageAvoidAutoSetImage` and implement your own after image load finished.
|
||||
|
||||
#if SD_UIKIT
|
||||
typedef UIViewAnimationOptions SDWebImageAnimationOptions;
|
||||
#else
|
||||
typedef NS_OPTIONS(NSUInteger, SDWebImageAnimationOptions) {
|
||||
SDWebImageAnimationOptionAllowsImplicitAnimation = 1 << 0, // specify `allowsImplicitAnimation` for the `NSAnimationContext`
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef void (^SDWebImageTransitionPreparesBlock)(__kindof UIView * _Nonnull view, UIImage * _Nullable image, NSData * _Nullable imageData, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
|
||||
typedef void (^SDWebImageTransitionAnimationsBlock)(__kindof UIView * _Nonnull view, UIImage * _Nullable image);
|
||||
typedef void (^SDWebImageTransitionCompletionBlock)(BOOL finished);
|
||||
|
||||
@interface SDWebImageTransition : NSObject
|
||||
|
||||
/**
|
||||
By default, we set the image to the view at the beginning of the animtions. You can disable this and provide custom set image process
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL avoidAutoSetImage;
|
||||
/**
|
||||
The duration of the transition animation, measured in seconds. Defaults to 0.5.
|
||||
*/
|
||||
@property (nonatomic, assign) NSTimeInterval duration;
|
||||
/**
|
||||
The timing function used for all animations within this transition animation (macOS).
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) CAMediaTimingFunction *timingFunction NS_AVAILABLE_MAC(10_7);
|
||||
/**
|
||||
A mask of options indicating how you want to perform the animations.
|
||||
*/
|
||||
@property (nonatomic, assign) SDWebImageAnimationOptions animationOptions;
|
||||
/**
|
||||
A block object to be executed before the animation sequence starts.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) SDWebImageTransitionPreparesBlock prepares;
|
||||
/**
|
||||
A block object that contains the changes you want to make to the specified view.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) SDWebImageTransitionAnimationsBlock animations;
|
||||
/**
|
||||
A block object to be executed when the animation sequence ends.
|
||||
*/
|
||||
@property (nonatomic, copy, nullable) SDWebImageTransitionCompletionBlock completion;
|
||||
|
||||
@end
|
||||
|
||||
// Convenience way to create transition. Remember to specify the duration
|
||||
// for UIKit, these transition just use the correspond `animationOptions`
|
||||
// for AppKit, these transition use Core Animation in `animations`. So your view must be layer-backed. Set `wantsLayer = YES` before you apply it.
|
||||
|
||||
@interface SDWebImageTransition (Conveniences)
|
||||
|
||||
// class property is available in Xcode 8. We will drop the Xcode 7.3 support in 5.x
|
||||
#if __has_feature(objc_class_property)
|
||||
/// Fade transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *fadeTransition;
|
||||
/// Flip from left transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromLeftTransition;
|
||||
/// Flip from right transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromRightTransition;
|
||||
/// Flip from top transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromTopTransition;
|
||||
/// Flip from bottom transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromBottomTransition;
|
||||
/// Curl up transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *curlUpTransition;
|
||||
/// Curl down transition.
|
||||
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *curlDownTransition;
|
||||
#else
|
||||
+ (nonnull instancetype)fadeTransition;
|
||||
+ (nonnull instancetype)flipFromLeftTransition;
|
||||
+ (nonnull instancetype)flipFromRightTransition;
|
||||
+ (nonnull instancetype)flipFromTopTransition;
|
||||
+ (nonnull instancetype)flipFromBottomTransition;
|
||||
+ (nonnull instancetype)curlUpTransition;
|
||||
+ (nonnull instancetype)curlDownTransition;
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDWebImageTransition.h"
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
|
||||
#if SD_MAC
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#endif
|
||||
|
||||
@implementation SDWebImageTransition
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.duration = 0.5;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDWebImageTransition (Conveniences)
|
||||
|
||||
+ (SDWebImageTransition *)fadeTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionCrossDissolve;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionFade;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
+ (SDWebImageTransition *)flipFromLeftTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromLeft;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromLeft;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
+ (SDWebImageTransition *)flipFromRightTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromRight;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromRight;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
+ (SDWebImageTransition *)flipFromTopTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromTop;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromTop;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
+ (SDWebImageTransition *)flipFromBottomTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionFlipFromBottom;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionPush;
|
||||
trans.subtype = kCATransitionFromBottom;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
+ (SDWebImageTransition *)curlUpTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionCurlUp;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionReveal;
|
||||
trans.subtype = kCATransitionFromTop;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
+ (SDWebImageTransition *)curlDownTransition {
|
||||
SDWebImageTransition *transition = [SDWebImageTransition new];
|
||||
#if SD_UIKIT
|
||||
transition.animationOptions = UIViewAnimationOptionTransitionCurlDown;
|
||||
#else
|
||||
transition.animations = ^(__kindof NSView * _Nonnull view, NSImage * _Nullable image) {
|
||||
CATransition *trans = [CATransition animation];
|
||||
trans.type = kCATransitionReveal;
|
||||
trans.subtype = kCATransitionFromBottom;
|
||||
[view.layer addAnimation:trans forKey:kCATransition];
|
||||
};
|
||||
#endif
|
||||
return transition;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -128,7 +128,7 @@
|
|||
options:(SDWebImageOptions)options
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock;
|
||||
|
||||
#pragma mark - Background image
|
||||
#pragma mark - Background Image
|
||||
|
||||
/**
|
||||
* Get the current background image URL.
|
||||
|
|
|
@ -26,22 +26,30 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
return [NSString stringWithFormat:@"backgroundImage_%lu", (unsigned long)state];
|
||||
}
|
||||
|
||||
static inline NSString * imageOperationKeyForState(UIControlState state) {
|
||||
return [NSString stringWithFormat:@"UIButtonImageOperation%lu", (unsigned long)state];
|
||||
}
|
||||
|
||||
static inline NSString * backgroundImageOperationKeyForState(UIControlState state) {
|
||||
return [NSString stringWithFormat:@"UIButtonBackgroundImageOperation%lu", (unsigned long)state];
|
||||
}
|
||||
|
||||
@implementation UIButton (WebCache)
|
||||
|
||||
#pragma mark - Image
|
||||
|
||||
- (nullable NSURL *)sd_currentImageURL {
|
||||
NSURL *url = self.imageURLStorage[imageURLKeyForState(self.state)];
|
||||
NSURL *url = self.sd_imageURLStorage[imageURLKeyForState(self.state)];
|
||||
|
||||
if (!url) {
|
||||
url = self.imageURLStorage[imageURLKeyForState(UIControlStateNormal)];
|
||||
url = self.sd_imageURLStorage[imageURLKeyForState(UIControlStateNormal)];
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
- (nullable NSURL *)sd_imageURLForState:(UIControlState)state {
|
||||
return self.imageURLStorage[imageURLKeyForState(state)];
|
||||
return self.sd_imageURLStorage[imageURLKeyForState(state)];
|
||||
}
|
||||
|
||||
- (void)sd_setImageWithURL:(nullable NSURL *)url forState:(UIControlState)state {
|
||||
|
@ -70,16 +78,16 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
options:(SDWebImageOptions)options
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
if (!url) {
|
||||
[self.imageURLStorage removeObjectForKey:imageURLKeyForState(state)];
|
||||
[self.sd_imageURLStorage removeObjectForKey:imageURLKeyForState(state)];
|
||||
} else {
|
||||
self.imageURLStorage[imageURLKeyForState(state)] = url;
|
||||
self.sd_imageURLStorage[imageURLKeyForState(state)] = url;
|
||||
}
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self sd_internalSetImageWithURL:url
|
||||
placeholderImage:placeholder
|
||||
options:options
|
||||
operationKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]
|
||||
operationKey:imageOperationKeyForState(state)
|
||||
setImageBlock:^(UIImage *image, NSData *imageData) {
|
||||
[weakSelf setImage:image forState:state];
|
||||
}
|
||||
|
@ -87,20 +95,20 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
completed:completedBlock];
|
||||
}
|
||||
|
||||
#pragma mark - Background image
|
||||
#pragma mark - Background Image
|
||||
|
||||
- (nullable NSURL *)sd_currentBackgroundImageURL {
|
||||
NSURL *url = self.imageURLStorage[backgroundImageURLKeyForState(self.state)];
|
||||
NSURL *url = self.sd_imageURLStorage[backgroundImageURLKeyForState(self.state)];
|
||||
|
||||
if (!url) {
|
||||
url = self.imageURLStorage[backgroundImageURLKeyForState(UIControlStateNormal)];
|
||||
url = self.sd_imageURLStorage[backgroundImageURLKeyForState(UIControlStateNormal)];
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
- (nullable NSURL *)sd_backgroundImageURLForState:(UIControlState)state {
|
||||
return self.imageURLStorage[backgroundImageURLKeyForState(state)];
|
||||
return self.sd_imageURLStorage[backgroundImageURLKeyForState(state)];
|
||||
}
|
||||
|
||||
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url forState:(UIControlState)state {
|
||||
|
@ -129,16 +137,16 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
options:(SDWebImageOptions)options
|
||||
completed:(nullable SDExternalCompletionBlock)completedBlock {
|
||||
if (!url) {
|
||||
[self.imageURLStorage removeObjectForKey:backgroundImageURLKeyForState(state)];
|
||||
[self.sd_imageURLStorage removeObjectForKey:backgroundImageURLKeyForState(state)];
|
||||
} else {
|
||||
self.imageURLStorage[backgroundImageURLKeyForState(state)] = url;
|
||||
self.sd_imageURLStorage[backgroundImageURLKeyForState(state)] = url;
|
||||
}
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self sd_internalSetImageWithURL:url
|
||||
placeholderImage:placeholder
|
||||
options:options
|
||||
operationKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]
|
||||
operationKey:backgroundImageOperationKeyForState(state)
|
||||
setImageBlock:^(UIImage *image, NSData *imageData) {
|
||||
[weakSelf setBackgroundImage:image forState:state];
|
||||
}
|
||||
|
@ -146,15 +154,19 @@ static inline NSString * backgroundImageURLKeyForState(UIControlState state) {
|
|||
completed:completedBlock];
|
||||
}
|
||||
|
||||
#pragma mark - Cancel
|
||||
|
||||
- (void)sd_cancelImageLoadForState:(UIControlState)state {
|
||||
[self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonImageOperation%@", @(state)]];
|
||||
[self sd_cancelImageLoadOperationWithKey:imageOperationKeyForState(state)];
|
||||
}
|
||||
|
||||
- (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state {
|
||||
[self sd_cancelImageLoadOperationWithKey:[NSString stringWithFormat:@"UIButtonBackgroundImageOperation%@", @(state)]];
|
||||
[self sd_cancelImageLoadOperationWithKey:backgroundImageOperationKeyForState(state)];
|
||||
}
|
||||
|
||||
- (SDStateImageURLDictionary *)imageURLStorage {
|
||||
#pragma mark - Private
|
||||
|
||||
- (SDStateImageURLDictionary *)sd_imageURLStorage {
|
||||
SDStateImageURLDictionary *storage = objc_getAssociatedObject(self, &imageURLStorageKey);
|
||||
if (!storage) {
|
||||
storage = [NSMutableDictionary dictionary];
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#import "SDWebImageDefine.h"
|
||||
#import "SDWebImageManager.h"
|
||||
#import "SDWebImageTransition.h"
|
||||
|
||||
/**
|
||||
The value specify that the image progress unit count cannot be determined because the progressBlock is not been called.
|
||||
|
@ -97,6 +98,14 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
|
|||
*/
|
||||
- (void)sd_cancelCurrentImageLoad;
|
||||
|
||||
#pragma mark - Image Transition
|
||||
|
||||
/**
|
||||
The image transition when image load finished. See `SDWebImageTransition`.
|
||||
If you specify nil, do not do transition. Defautls to nil.
|
||||
*/
|
||||
@property (nonatomic, strong, nullable) SDWebImageTransition *sd_imageTransition;
|
||||
|
||||
#if SD_UIKIT
|
||||
|
||||
#pragma mark - Activity indicator
|
||||
|
|
|
@ -145,11 +145,17 @@ static char TAG_ACTIVITY_SHOW;
|
|||
targetData = nil;
|
||||
}
|
||||
|
||||
// check whether we should use the image transition
|
||||
SDWebImageTransition *transition = nil;
|
||||
if (finished && (options & SDWebImageForceTransition || cacheType == SDImageCacheTypeNone)) {
|
||||
transition = sself.sd_imageTransition;
|
||||
}
|
||||
|
||||
if ([context valueForKey:SDWebImageContextSetImageGroup]) {
|
||||
dispatch_group_t group = [context valueForKey:SDWebImageContextSetImageGroup];
|
||||
dispatch_group_enter(group);
|
||||
dispatch_main_async_safe(^{
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
|
||||
});
|
||||
// ensure completion block is called after custom setImage process finish
|
||||
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
|
||||
|
@ -157,7 +163,7 @@ static char TAG_ACTIVITY_SHOW;
|
|||
});
|
||||
} else {
|
||||
dispatch_main_async_safe(^{
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock];
|
||||
[sself sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
|
||||
callCompletedBlockClojure();
|
||||
});
|
||||
}
|
||||
|
@ -179,24 +185,79 @@ static char TAG_ACTIVITY_SHOW;
|
|||
}
|
||||
|
||||
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock {
|
||||
[self sd_setImage:image imageData:imageData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:nil cacheType:0 imageURL:nil];
|
||||
}
|
||||
|
||||
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock transition:(SDWebImageTransition *)transition cacheType:(SDImageCacheType)cacheType imageURL:(NSURL *)imageURL {
|
||||
UIView *view = self;
|
||||
SDSetImageBlock finalSetImageBlock;
|
||||
if (setImageBlock) {
|
||||
setImageBlock(image, imageData);
|
||||
return;
|
||||
finalSetImageBlock = setImageBlock;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_MAC
|
||||
if ([self isKindOfClass:[UIImageView class]]) {
|
||||
UIImageView *imageView = (UIImageView *)self;
|
||||
imageView.image = image;
|
||||
else if ([view isKindOfClass:[UIImageView class]]) {
|
||||
UIImageView *imageView = (UIImageView *)view;
|
||||
finalSetImageBlock = ^(UIImage *setImage, NSData *setImageData) {
|
||||
imageView.image = setImage;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#if SD_UIKIT
|
||||
else if ([view isKindOfClass:[UIButton class]]) {
|
||||
UIButton *button = (UIButton *)view;
|
||||
finalSetImageBlock = ^(UIImage *setImage, NSData *setImageData){
|
||||
[button setImage:setImage forState:UIControlStateNormal];
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (transition) {
|
||||
#if SD_UIKIT
|
||||
if ([self isKindOfClass:[UIButton class]]) {
|
||||
UIButton *button = (UIButton *)self;
|
||||
[button setImage:image forState:UIControlStateNormal];
|
||||
}
|
||||
[UIView transitionWithView:view duration:0 options:0 animations:^{
|
||||
// 0 duration to let UIKit render placeholder and prepares block
|
||||
if (transition.prepares) {
|
||||
transition.prepares(view, image, imageData, cacheType, imageURL);
|
||||
}
|
||||
} completion:^(BOOL finished) {
|
||||
[UIView transitionWithView:view duration:transition.duration options:transition.animationOptions animations:^{
|
||||
if (finalSetImageBlock && !transition.avoidAutoSetImage) {
|
||||
finalSetImageBlock(image, imageData);
|
||||
}
|
||||
if (transition.animations) {
|
||||
transition.animations(view, image);
|
||||
}
|
||||
} completion:transition.completion];
|
||||
}];
|
||||
#elif SD_MAC
|
||||
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull prepareContext) {
|
||||
// 0 duration to let AppKit render placeholder and prepares block
|
||||
prepareContext.duration = 0;
|
||||
if (transition.prepares) {
|
||||
transition.prepares(view, image, imageData, cacheType, imageURL);
|
||||
}
|
||||
} completionHandler:^{
|
||||
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
|
||||
context.duration = transition.duration;
|
||||
context.timingFunction = transition.timingFunction;
|
||||
context.allowsImplicitAnimation = (transition.animationOptions & SDWebImageAnimationOptionAllowsImplicitAnimation);
|
||||
if (finalSetImageBlock && !transition.avoidAutoSetImage) {
|
||||
finalSetImageBlock(image, imageData);
|
||||
}
|
||||
if (transition.animations) {
|
||||
transition.animations(view, image);
|
||||
}
|
||||
} completionHandler:^{
|
||||
if (transition.completion) {
|
||||
transition.completion(YES);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
#endif
|
||||
} else {
|
||||
if (finalSetImageBlock) {
|
||||
finalSetImageBlock(image, imageData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sd_setNeedsLayout {
|
||||
|
@ -207,6 +268,15 @@ static char TAG_ACTIVITY_SHOW;
|
|||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - Image Transition
|
||||
- (SDWebImageTransition *)sd_imageTransition {
|
||||
return objc_getAssociatedObject(self, @selector(sd_imageTransition));
|
||||
}
|
||||
|
||||
- (void)setSd_imageTransition:(SDWebImageTransition *)sd_imageTransition {
|
||||
objc_setAssociatedObject(self, @selector(sd_imageTransition), sd_imageTransition, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
|
||||
#pragma mark - Activity indicator
|
||||
|
||||
#pragma mark -
|
||||
|
|
|
@ -35,6 +35,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[];
|
|||
#import <SDWebImage/UIImage+MultiFormat.h>
|
||||
#import <SDWebImage/SDWebImageOperation.h>
|
||||
#import <SDWebImage/SDWebImageDownloader.h>
|
||||
#import <SDWebImage/SDWebImageTransition.h>
|
||||
|
||||
#if SD_MAC || SD_UIKIT
|
||||
#import <SDWebImage/MKAnnotationView+WebCache.h>
|
||||
|
@ -55,6 +56,7 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[];
|
|||
|
||||
#if SD_MAC
|
||||
#import <SDWebImage/NSImage+Additions.h>
|
||||
#import <SDWebImage/NSButton+WebCache.h>
|
||||
#endif
|
||||
|
||||
#if SD_UIKIT
|
||||
|
|
Loading…
Reference in New Issue