Commit 9ada19e9 cgx

webp图片加载、微信相关跳转、关于我们、CBTI等

1 个父辈 b6cd9f3c
正在显示 102 个修改的文件 包含 4534 行增加25 行删除
......@@ -16,6 +16,7 @@
D01814E8280020F900583D4E /* CWPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814E6280020F800583D4E /* CWPageControl.m */; };
D01814EB28002A8200583D4E /* DsMiddleView.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814EA28002A8200583D4E /* DsMiddleView.m */; };
D01814EE28002DC700583D4E /* HeaderDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = D01814ED28002DC700583D4E /* HeaderDataModel.m */; };
D020CE1F280D951400E7E82F /* invite_friend.webp in Resources */ = {isa = PBXBuildFile; fileRef = D020CE1E280D915D00E7E82F /* invite_friend.webp */; };
D027EE2627FB3DC0004BBA61 /* NetLoadingStateView.m in Sources */ = {isa = PBXBuildFile; fileRef = D027EE2527FB3DC0004BBA61 /* NetLoadingStateView.m */; };
D027EE2927FB51D0004BBA61 /* DSGifHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D027EE2827FB51D0004BBA61 /* DSGifHeader.m */; };
D027EE3027FB52DA004BBA61 /* UIImage+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = D027EE2F27FB52DA004BBA61 /* UIImage+Extras.m */; };
......@@ -44,6 +45,7 @@
D0930F1B2801874B006B497A /* UINavigationController+Pop.m in Sources */ = {isa = PBXBuildFile; fileRef = D0930F182801874B006B497A /* UINavigationController+Pop.m */; };
D09D0E96280D3FE9008DEDAB /* NSDate+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = D09D0E95280D3FE9008DEDAB /* NSDate+Extras.m */; };
D09D0E9A280D507F008DEDAB /* ProfileAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = D09D0E99280D507F008DEDAB /* ProfileAlertView.m */; };
D09D0E9D280D73B6008DEDAB /* InviteController.m in Sources */ = {isa = PBXBuildFile; fileRef = D09D0E9C280D73B6008DEDAB /* InviteController.m */; };
D0B5ECA627F2D9DE003EDFE3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */; };
D0B5ECAF27F2D9DE003EDFE3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D0B5ECAD27F2D9DE003EDFE3 /* Main.storyboard */; };
D0B5ECB127F2D9E0003EDFE3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D0B5ECB027F2D9E0003EDFE3 /* Assets.xcassets */; };
......@@ -103,6 +105,7 @@
D01814EA28002A8200583D4E /* DsMiddleView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DsMiddleView.m; sourceTree = "<group>"; };
D01814EC28002DC700583D4E /* HeaderDataModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HeaderDataModel.h; sourceTree = "<group>"; };
D01814ED28002DC700583D4E /* HeaderDataModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HeaderDataModel.m; sourceTree = "<group>"; };
D020CE1E280D915D00E7E82F /* invite_friend.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = invite_friend.webp; sourceTree = "<group>"; };
D027EE2427FB3DC0004BBA61 /* NetLoadingStateView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetLoadingStateView.h; sourceTree = "<group>"; };
D027EE2527FB3DC0004BBA61 /* NetLoadingStateView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NetLoadingStateView.m; sourceTree = "<group>"; };
D027EE2727FB51D0004BBA61 /* DSGifHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSGifHeader.h; sourceTree = "<group>"; };
......@@ -157,6 +160,8 @@
D09D0E95280D3FE9008DEDAB /* NSDate+Extras.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+Extras.m"; sourceTree = "<group>"; };
D09D0E98280D507F008DEDAB /* ProfileAlertView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProfileAlertView.h; sourceTree = "<group>"; };
D09D0E99280D507F008DEDAB /* ProfileAlertView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ProfileAlertView.m; sourceTree = "<group>"; };
D09D0E9B280D73B6008DEDAB /* InviteController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = InviteController.h; sourceTree = "<group>"; };
D09D0E9C280D73B6008DEDAB /* InviteController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = InviteController.m; sourceTree = "<group>"; };
D0B5ECA127F2D9DE003EDFE3 /* DreamSleepDev.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DreamSleepDev.app; sourceTree = BUILT_PRODUCTS_DIR; };
D0B5ECA427F2D9DE003EDFE3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
......@@ -314,6 +319,7 @@
D04567A827F6D018009F0A82 /* Resource */ = {
isa = PBXGroup;
children = (
D020CE1E280D915D00E7E82F /* invite_friend.webp */,
D0C09ED428007D9100709D4C /* 478_lottie.json */,
D0C09ED528007D9100709D4C /* 478normal_lottie.json */,
D0C09ED628007D9100709D4C /* relax_lottie.json */,
......@@ -387,6 +393,8 @@
D0E660042807D02C006562F2 /* UserRequestModel.m */,
D09D0E98280D507F008DEDAB /* ProfileAlertView.h */,
D09D0E99280D507F008DEDAB /* ProfileAlertView.m */,
D09D0E9B280D73B6008DEDAB /* InviteController.h */,
D09D0E9C280D73B6008DEDAB /* InviteController.m */,
);
path = Profile;
sourceTree = "<group>";
......@@ -694,6 +702,7 @@
D0C09ED828007D9100709D4C /* 478_lottie.json in Resources */,
D04B3DB327F6F6070022F8DF /* Home.storyboard in Resources */,
D027EE3227FB5464004BBA61 /* pull_down.gif in Resources */,
D020CE1F280D951400E7E82F /* invite_friend.webp in Resources */,
D07F9DE927F4683B0036372F /* DKColorTable.txt in Resources */,
D0B5ECB427F2D9E0003EDFE3 /* LaunchScreen.storyboard in Resources */,
D0B5ECB127F2D9E0003EDFE3 /* Assets.xcassets in Resources */,
......@@ -757,6 +766,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D09D0E9D280D73B6008DEDAB /* InviteController.m in Sources */,
D04B3D9A27F6D4D90022F8DF /* LeadingController.m in Sources */,
D0B5ECD827F2F1B0003EDFE3 /* ServerAPIUtil.m in Sources */,
D0B5ECA627F2D9DE003EDFE3 /* AppDelegate.m in Sources */,
......
//
// InviteController.h
// DreamSleep
//
// Created by peter on 2022/4/18.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface InviteController : UIViewController
@end
NS_ASSUME_NONNULL_END
//
// InviteController.m
// DreamSleep
//
// Created by peter on 2022/4/18.
//
#import "InviteController.h"
#import <YYWebImage/YYWebImage.h>
@interface InviteController ()
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) YYAnimatedImageView *animatedView;
@end
@implementation InviteController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"邀请好友";
self.view.backgroundColor = DSWhite;
[self.view addSubview:self.scrollView];
UIButton *shareBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[shareBtn setImage:[UIImage imageNamed:@"shareIcon"] forState:UIControlStateNormal];
[shareBtn addTarget:self action:@selector(shareAction) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:shareBtn];
}
- (void)shareAction {
}
- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight - kTopHeight(0))];
[_scrollView addSubview:self.animatedView];
}
return _scrollView;
}
- (YYAnimatedImageView *)animatedView {
if (!_animatedView) {
_animatedView = [[YYAnimatedImageView alloc] initWithFrame:self.scrollView.bounds];
NSString *path = [[NSBundle mainBundle] pathForAuxiliaryExecutable:@"invite_friend.webp"];
_animatedView.yy_imageURL = [NSURL fileURLWithPath:path];
}
return _animatedView;
}
@end
......@@ -124,27 +124,26 @@
case 5: // 前往小程序
{
WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
launchMiniProgramReq.userName = @"小梦睡眠";
launchMiniProgramReq.userName = @"gh_cb2b2c83afc8";
launchMiniProgramReq.miniProgramType = WXMiniProgramTypeRelease;
[WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) {
}];
}
break;
case 6: // 关注公众号
{
WXOpenBusinessViewReq *req = [WXOpenBusinessViewReq object];
[WXApi sendReq:req completion:^(BOOL success) {
}];
NSURL *wxURL = [NSURL URLWithString:@"weixin://"];
if ([[UIApplication sharedApplication] canOpenURL:wxURL]) {
[[UIApplication sharedApplication] openURL:wxURL options:@{} completionHandler:nil];
}
}
break;
case 7: // 添加客服微信
{
WXOpenCustomerServiceReq *req = [[WXOpenCustomerServiceReq alloc] init];
req.corpid = @""; // 企业ID
req.url = @""; // 客服URL
[WXApi sendReq:req completion:^(BOOL success) {
}];
NSURL *wxURL = [NSURL URLWithString:@"weixin://"];
if ([[UIApplication sharedApplication] canOpenURL:wxURL]) {
[[UIApplication sharedApplication] openURL:wxURL options:@{} completionHandler:nil];
}
}
break;
default:
......
......@@ -8,6 +8,7 @@
#import "ProfileController.h"
#import "SystemSetController.h"
#import "LoginController.h"
#import "InviteController.h"
#import "PrivacyViewController.h"
#import "ProfileAlertView.h"
......@@ -65,11 +66,17 @@
[self.navigationController pushViewController:sysVC animated:YES];
}
break;
case 3: // 邀请好友
{
InviteController *inviteVC = [InviteController new];
[self.navigationController pushViewController:inviteVC animated:YES];
}
break;
case 4: // 关于我们
{
[self.navigationController pushViewController:[[PrivacyViewController alloc] initWithTitle:@"关于我们" link:[NSURL URLWithString:PrivacyPolicy] isDetail:YES] animated:YES];
[self.navigationController pushViewController:[[PrivacyViewController alloc] initWithTitle:@"关于我们" link:[NSURL URLWithString:AboutUS] isDetail:YES] animated:YES];
}
break;;
break;
case 5: // 前往小程序
{
[[[ProfileAlertView alloc] initWithIndexPath:indexPath] showAlertView];
......@@ -77,16 +84,21 @@
break;
case 6: // 关注公众号
{
[UIPasteboard generalPasteboard].string = @"公众号名称";
[UIPasteboard generalPasteboard].string = @"xiaomeng-sleep";
[[[ProfileAlertView alloc] initWithIndexPath:indexPath] showAlertView];
}
break;
case 7: // 添加客服微信
{
[UIPasteboard generalPasteboard].string = @"客服微信";
[UIPasteboard generalPasteboard].string = @"xiaomengsleep";
[[[ProfileAlertView alloc] initWithIndexPath:indexPath] showAlertView];
}
break;
case 8: // CBTI
{
[self.navigationController pushViewController:[[PrivacyViewController alloc] initWithTitle:@"失眠的认知行为疗法(CBTI)" link:[NSURL URLWithString:MYCBTI] isDetail:YES] animated:YES];
}
break;;
default:
break;
}
......
{
"images" : [
{
"filename" : "shareIcon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "shareIcon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "shareIcon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -18,6 +18,11 @@ FOUNDATION_EXTERN NSString * const FirstShowPrivacy;
// 引导页
FOUNDATION_EXTERN NSString * const IsFirstGuide;
// 关于我们
FOUNDATION_EXTERN NSString * const AboutUS;
// 失眠的认知行为疗法
FOUNDATION_EXTERN NSString * const MYCBTI;
// 主体模式自动切换标记
FOUNDATION_EXTERN NSString * const ThemeAutoSwitch;
FOUNDATION_EXTERN NSString * const StartTime1;
......
......@@ -14,6 +14,9 @@ NSString * const FirstShowPrivacy = @"FirstShowPrivacy";
NSString * const IsFirstGuide = @"isFirstGuide";
NSString * const AboutUS = @"https://www.cbti.cn/sleep/user/about";
NSString * const MYCBTI = @"https://www.cbti.cn/sleep/ssmian/cbti";
NSString * const ThemeAutoSwitch = @"themeAutoSwitch";
NSString * const StartTime1 = @"21:00:00";
NSString * const ExpireTime1 = @"23:59:59";
......
......@@ -9,6 +9,8 @@ target 'DreamSleep' do
pod 'lottie-ios', '~> 2.5.3'
pod 'DOUAudioStreamer', '~> 0.2.16'
pod 'MBProgressHUD', '~> 1.2.0'
pod 'YYWebImage', '~> 1.0.5'
pod 'YYImage/WebP'
end
# AFNetworking (4.0.1)
......@@ -19,3 +21,5 @@ end
# lottie-ios (2.5.3)
# DOUAudioStreamer (0.2.16)
# MBProgressHUD (1.2.0)
# YYWebImage (1.0.5)
# YYImage/WebP
......@@ -26,6 +26,15 @@ PODS:
- MJRefresh (3.7.5)
- YTKNetwork (3.0.6):
- AFNetworking/NSURLSession (~> 4.0)
- YYCache (1.0.4)
- YYImage (1.0.4):
- YYImage/Core (= 1.0.4)
- YYImage/Core (1.0.4)
- YYImage/WebP (1.0.4):
- YYImage/Core
- YYWebImage (1.0.5):
- YYCache
- YYImage
DEPENDENCIES:
- DKNightVersion (~> 2.4.3)
......@@ -35,6 +44,8 @@ DEPENDENCIES:
- MBProgressHUD (~> 1.2.0)
- MJRefresh (~> 3.7.5)
- YTKNetwork (~> 3.0.6)
- YYImage/WebP
- YYWebImage (~> 1.0.5)
SPEC REPOS:
trunk:
......@@ -46,6 +57,9 @@ SPEC REPOS:
- MBProgressHUD
- MJRefresh
- YTKNetwork
- YYCache
- YYImage
- YYWebImage
SPEC CHECKSUMS:
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
......@@ -56,7 +70,10 @@ SPEC CHECKSUMS:
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04
YYCache: 8105b6638f5e849296c71f331ff83891a4942952
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928
PODFILE CHECKSUM: a104f44701b575581b7616430c2ac814555ec002
PODFILE CHECKSUM: 462801539eac1a9c9c847595e3687fd361bff7ed
COCOAPODS: 1.11.3
......@@ -26,6 +26,15 @@ PODS:
- MJRefresh (3.7.5)
- YTKNetwork (3.0.6):
- AFNetworking/NSURLSession (~> 4.0)
- YYCache (1.0.4)
- YYImage (1.0.4):
- YYImage/Core (= 1.0.4)
- YYImage/Core (1.0.4)
- YYImage/WebP (1.0.4):
- YYImage/Core
- YYWebImage (1.0.5):
- YYCache
- YYImage
DEPENDENCIES:
- DKNightVersion (~> 2.4.3)
......@@ -35,6 +44,8 @@ DEPENDENCIES:
- MBProgressHUD (~> 1.2.0)
- MJRefresh (~> 3.7.5)
- YTKNetwork (~> 3.0.6)
- YYImage/WebP
- YYWebImage (~> 1.0.5)
SPEC REPOS:
trunk:
......@@ -46,6 +57,9 @@ SPEC REPOS:
- MBProgressHUD
- MJRefresh
- YTKNetwork
- YYCache
- YYImage
- YYWebImage
SPEC CHECKSUMS:
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
......@@ -56,7 +70,10 @@ SPEC CHECKSUMS:
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04
YYCache: 8105b6638f5e849296c71f331ff83891a4942952
YYImage: 1e1b62a9997399593e4b9c4ecfbbabbf1d3f3b54
YYWebImage: 5f7f36aee2ae293f016d418c7d6ba05c4863e928
PODFILE CHECKSUM: a104f44701b575581b7616430c2ac814555ec002
PODFILE CHECKSUM: 462801539eac1a9c9c847595e3687fd361bff7ed
COCOAPODS: 1.11.3
......@@ -175,6 +175,84 @@ THE SOFTWARE.
## YYCache
The MIT License (MIT)
Copyright (c) 2015 ibireme <ibireme@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## YYImage
The MIT License (MIT)
Copyright (c) 2015 ibireme <ibireme@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## YYWebImage
The MIT License (MIT)
Copyright (c) 2015 ibireme <ibireme@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## lottie-ios
Apache License
......
......@@ -230,6 +230,102 @@ THE SOFTWARE.
</dict>
<dict>
<key>FooterText</key>
<string>The MIT License (MIT)
Copyright (c) 2015 ibireme &lt;ibireme@gmail.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>YYCache</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>The MIT License (MIT)
Copyright (c) 2015 ibireme &lt;ibireme@gmail.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>YYImage</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>The MIT License (MIT)
Copyright (c) 2015 ibireme &lt;ibireme@gmail.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>YYWebImage</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string> Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
......
......@@ -6,4 +6,7 @@ ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework
${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework
${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
\ No newline at end of file
......@@ -5,4 +5,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYWebImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
\ No newline at end of file
......@@ -6,4 +6,7 @@ ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework
${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework
${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
\ No newline at end of file
......@@ -5,4 +5,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYWebImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
\ No newline at end of file
......@@ -6,4 +6,7 @@ ${BUILT_PRODUCTS_DIR}/MBProgressHUD/MBProgressHUD.framework
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework
${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework
${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
\ No newline at end of file
......@@ -5,4 +5,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MBProgressHUD.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYWebImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
\ No newline at end of file
......@@ -183,6 +183,9 @@ if [[ "$CONFIGURATION" == "Beta" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
fi
if [[ "$CONFIGURATION" == "Debug" ]]; then
......@@ -193,6 +196,9 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
fi
if [[ "$CONFIGURATION" == "Release" ]]; then
......@@ -203,6 +209,9 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYWebImage/YYWebImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
fi
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer/DOUAudioStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer/DOUAudioStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache/YYCache.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage/YYWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreAudio" -framework "CoreGraphics" -framework "DKNightVersion" -framework "DOUAudioStreamer" -framework "Foundation" -framework "Lottie" -framework "MBProgressHUD" -framework "MJRefresh" -framework "Masonry" -framework "MediaPlayer" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -framework "YTKNetwork"
OTHER_LDFLAGS = $(inherited) -ObjC -l"sqlite3" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AssetsLibrary" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreAudio" -framework "CoreFoundation" -framework "CoreGraphics" -framework "DKNightVersion" -framework "DOUAudioStreamer" -framework "Foundation" -framework "ImageIO" -framework "Lottie" -framework "MBProgressHUD" -framework "MJRefresh" -framework "Masonry" -framework "MediaPlayer" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -framework "YTKNetwork" -framework "YYCache" -framework "YYImage" -framework "YYWebImage"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer/DOUAudioStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer/DOUAudioStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache/YYCache.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage/YYWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreAudio" -framework "CoreGraphics" -framework "DKNightVersion" -framework "DOUAudioStreamer" -framework "Foundation" -framework "Lottie" -framework "MBProgressHUD" -framework "MJRefresh" -framework "Masonry" -framework "MediaPlayer" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -framework "YTKNetwork"
OTHER_LDFLAGS = $(inherited) -ObjC -l"sqlite3" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AssetsLibrary" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreAudio" -framework "CoreFoundation" -framework "CoreGraphics" -framework "DKNightVersion" -framework "DOUAudioStreamer" -framework "Foundation" -framework "ImageIO" -framework "Lottie" -framework "MBProgressHUD" -framework "MJRefresh" -framework "Masonry" -framework "MediaPlayer" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -framework "YTKNetwork" -framework "YYCache" -framework "YYImage" -framework "YYWebImage"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios" "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer/DOUAudioStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DOUAudioStreamer/DOUAudioStreamer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache/YYCache.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage/YYImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage/YYWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreAudio" -framework "CoreGraphics" -framework "DKNightVersion" -framework "DOUAudioStreamer" -framework "Foundation" -framework "Lottie" -framework "MBProgressHUD" -framework "MJRefresh" -framework "Masonry" -framework "MediaPlayer" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -framework "YTKNetwork"
OTHER_LDFLAGS = $(inherited) -ObjC -l"sqlite3" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AssetsLibrary" -framework "AudioToolbox" -framework "CFNetwork" -framework "CoreAudio" -framework "CoreFoundation" -framework "CoreGraphics" -framework "DKNightVersion" -framework "DOUAudioStreamer" -framework "Foundation" -framework "ImageIO" -framework "Lottie" -framework "MBProgressHUD" -framework "MJRefresh" -framework "Masonry" -framework "MediaPlayer" -framework "MobileCoreServices" -framework "OpenGLES" -framework "QuartzCore" -framework "UIKit" -framework "YTKNetwork" -framework "YYCache" -framework "YYImage" -framework "YYWebImage"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.4</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_YYCache : NSObject
@end
@implementation PodsDummy_YYCache
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "YYCache.h"
#import "YYDiskCache.h"
#import "YYKVStorage.h"
#import "YYMemoryCache.h"
FOUNDATION_EXPORT double YYCacheVersionNumber;
FOUNDATION_EXPORT const unsigned char YYCacheVersionString[];
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYCache
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"sqlite3" -framework "CoreFoundation" -framework "QuartzCore" -framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/YYCache
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
framework module YYCache {
umbrella header "YYCache-umbrella.h"
export *
module * { export * }
}
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYCache
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"sqlite3" -framework "CoreFoundation" -framework "QuartzCore" -framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/YYCache
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.4</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_YYImage : NSObject
@end
@implementation PodsDummy_YYImage
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "YYAnimatedImageView.h"
#import "YYFrameImage.h"
#import "YYImage.h"
#import "YYImageCoder.h"
#import "YYSpriteSheetImage.h"
FOUNDATION_EXPORT double YYImageVersionNumber;
FOUNDATION_EXPORT const unsigned char YYImageVersionString[];
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYImage
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"z" -framework "Accelerate" -framework "AssetsLibrary" -framework "CoreFoundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -framework "UIKit" -framework "WebP"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/YYImage
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
framework module YYImage {
umbrella header "YYImage-umbrella.h"
export *
module * { export * }
}
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYImage
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"z" -framework "Accelerate" -framework "AssetsLibrary" -framework "CoreFoundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -framework "UIKit" -framework "WebP"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/YYImage
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.5</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_YYWebImage : NSObject
@end
@implementation PodsDummy_YYWebImage
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "YYImageCache.h"
#import "YYWebImage.h"
#import "YYWebImageManager.h"
#import "YYWebImageOperation.h"
#import "CALayer+YYWebImage.h"
#import "MKAnnotationView+YYWebImage.h"
#import "UIButton+YYWebImage.h"
#import "UIImage+YYWebImage.h"
#import "UIImageView+YYWebImage.h"
FOUNDATION_EXPORT double YYWebImageVersionNumber;
FOUNDATION_EXPORT const unsigned char YYWebImageVersionString[];
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "AssetsLibrary" -framework "CoreFoundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -framework "UIKit" -framework "YYCache" -framework "YYImage"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/YYWebImage
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
framework module YYWebImage {
umbrella header "YYWebImage-umbrella.h"
export *
module * { export * }
}
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYWebImage
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" "${PODS_CONFIGURATION_BUILD_DIR}/YYImage" "${PODS_ROOT}/YYImage/Vendor"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "AssetsLibrary" -framework "CoreFoundation" -framework "ImageIO" -framework "MobileCoreServices" -framework "QuartzCore" -framework "UIKit" -framework "YYCache" -framework "YYImage"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/YYWebImage
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
The MIT License (MIT)
Copyright (c) 2015 ibireme <ibireme@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
YYCache
==============
[![License MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/ibireme/YYCache/master/LICENSE)&nbsp;
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)&nbsp;
[![CocoaPods](http://img.shields.io/cocoapods/v/YYCache.svg?style=flat)](http://cocoapods.org/?q= YYCache)&nbsp;
[![CocoaPods](http://img.shields.io/cocoapods/p/YYCache.svg?style=flat)](http://cocoapods.org/?q= YYCache)&nbsp;
[![Support](https://img.shields.io/badge/support-iOS%206%2B%20-blue.svg?style=flat)](https://www.apple.com/nl/ios/)&nbsp;
[![Build Status](https://travis-ci.org/ibireme/YYCache.svg?branch=master)](https://travis-ci.org/ibireme/YYCache)
High performance cache framework for iOS.<br/>
(It's a component of [YYKit](https://github.com/ibireme/YYKit))
Performance
==============
![Memory cache benchmark result](https://raw.github.com/ibireme/YYCache/master/Benchmark/Result_memory.png
)
![Disk benchmark result](https://raw.github.com/ibireme/YYCache/master/Benchmark/Result_disk.png
)
You may [download](http://www.sqlite.org/download.html) and compile the latest version of sqlite and ignore the libsqlite3.dylib in iOS system to get higher performance.
See `Benchmark/CacheBenchmark.xcodeproj` for more benchmark case.
Features
==============
- **LRU**: Objects can be evicted with least-recently-used algorithm.
- **Limitation**: Cache limitation can be controlled with count, cost, age and free space.
- **Compatibility**: The API is similar to `NSCache`, all methods are thread-safe.
- **Memory Cache**
- **Release Control**: Objects can be released synchronously/asynchronously on main thread or background thread.
- **Automatically Clear**: It can be configured to automatically evict objects when receive memory warning or app enter background.
- **Disk Cache**
- **Customization**: It supports custom archive and unarchive method to store object which does not adopt NSCoding.
- **Storage Type Control**: It can automatically decide the storage type (sqlite / file) for each object to get
better performance.
Installation
==============
### CocoaPods
1. Add `pod 'YYCache'` to your Podfile.
2. Run `pod install` or `pod update`.
3. Import \<YYCache/YYCache.h\>.
### Carthage
1. Add `github "ibireme/YYCache"` to your Cartfile.
2. Run `carthage update --platform ios` and add the framework to your project.
3. Import \<YYCache/YYCache.h\>.
### Manually
1. Download all the files in the YYCache subdirectory.
2. Add the source files to your Xcode project.
3. Link with required frameworks:
* UIKit
* CoreFoundation
* QuartzCore
* sqlite3
4. Import `YYCache.h`.
Documentation
==============
Full API documentation is available on [CocoaDocs](http://cocoadocs.org/docsets/YYCache/).<br/>
You can also install documentation locally using [appledoc](https://github.com/tomaz/appledoc).
Requirements
==============
This library requires `iOS 6.0+` and `Xcode 7.0+`.
License
==============
YYCache is provided under the MIT license. See LICENSE file for details.
<br/><br/>
---
中文介绍
==============
高性能 iOS 缓存框架。<br/>
(该项目是 [YYKit](https://github.com/ibireme/YYKit) 组件之一)
性能
==============
iPhone 6 上,内存缓存每秒响应次数 (越高越好):
![Memory cache benchmark result](https://raw.github.com/ibireme/YYCache/master/Benchmark/Result_memory.png
)
iPhone 6 上,磁盘缓存每秒响应次数 (越高越好):
![Disk benchmark result](https://raw.github.com/ibireme/YYCache/master/Benchmark/Result_disk.png
)
推荐到 SQLite 官网[下载](http://www.sqlite.org/download.html)和编译最新的 SQLite,以替换 iOS 自带的 libsqlite3.dylib,以获得最高 1.5~3 倍的性能提升。
更多测试代码和用例见 `Benchmark/CacheBenchmark.xcodeproj`
特性
==============
- **LRU**: 缓存支持 LRU (least-recently-used) 淘汰算法。
- **缓存控制**: 支持多种缓存控制方法:总数量、总大小、存活时间、空闲空间。
- **兼容性**: API 基本和 `NSCache` 保持一致, 所有方法都是线程安全的。
- **内存缓存**
- **对象释放控制**: 对象的释放(release) 可以配置为同步或异步进行,可以配置在主线程或后台线程进行。
- **自动清空**: 当收到内存警告或 App 进入后台时,缓存可以配置为自动清空。
- **磁盘缓存**
- **可定制性**: 磁盘缓存支持自定义的归档解档方法,以支持那些没有实现 NSCoding 协议的对象。
- **存储类型控制**: 磁盘缓存支持对每个对象的存储类型 (SQLite/文件) 进行自动或手动控制,以获得更高的存取性能。
安装
==============
### CocoaPods
1. 在 Podfile 中添加 `pod 'YYCache'`
2. 执行 `pod install``pod update`
3. 导入 \<YYCache/YYCache.h\>
### Carthage
1. 在 Cartfile 中添加 `github "ibireme/YYCache"`
2. 执行 `carthage update --platform ios` 并将生成的 framework 添加到你的工程。
3. 导入 \<YYCache/YYCache.h\>
### 手动安装
1. 下载 YYCache 文件夹内的所有内容。
2. 将 YYCache 内的源文件添加(拖放)到你的工程。
3. 链接以下的 frameworks:
* UIKit
* CoreFoundation
* QuartzCore
* sqlite3
4. 导入 `YYCache.h`
文档
==============
你可以在 [CocoaDocs](http://cocoadocs.org/docsets/YYCache/) 查看在线 API 文档,也可以用 [appledoc](https://github.com/tomaz/appledoc) 本地生成文档。
系统要求
==============
该项目最低支持 `iOS 6.0``Xcode 7.0`
许可证
==============
YYCache 使用 MIT 许可证,详情见 LICENSE 文件。
相关链接
==============
[YYCache 设计思路与技术细节](http://blog.ibireme.com/2015/10/26/yycache/)
//
// YYCache.h
// YYCache <https://github.com/ibireme/YYCache>
//
// Created by ibireme on 15/2/13.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <Foundation/Foundation.h>
#if __has_include(<YYCache/YYCache.h>)
FOUNDATION_EXPORT double YYCacheVersionNumber;
FOUNDATION_EXPORT const unsigned char YYCacheVersionString[];
#import <YYCache/YYMemoryCache.h>
#import <YYCache/YYDiskCache.h>
#import <YYCache/YYKVStorage.h>
#elif __has_include(<YYWebImage/YYCache.h>)
#import <YYWebImage/YYMemoryCache.h>
#import <YYWebImage/YYDiskCache.h>
#import <YYWebImage/YYKVStorage.h>
#else
#import "YYMemoryCache.h"
#import "YYDiskCache.h"
#import "YYKVStorage.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
`YYCache` is a thread safe key-value cache.
It use `YYMemoryCache` to store objects in a small and fast memory cache,
and use `YYDiskCache` to persisting objects to a large and slow disk cache.
See `YYMemoryCache` and `YYDiskCache` for more information.
*/
@interface YYCache : NSObject
/** The name of the cache, readonly. */
@property (copy, readonly) NSString *name;
/** The underlying memory cache. see `YYMemoryCache` for more information.*/
@property (strong, readonly) YYMemoryCache *memoryCache;
/** The underlying disk cache. see `YYDiskCache` for more information.*/
@property (strong, readonly) YYDiskCache *diskCache;
/**
Create a new instance with the specified name.
Multiple instances with the same name will make the cache unstable.
@param name The name of the cache. It will create a dictionary with the name in
the app's caches dictionary for disk cache. Once initialized you should not
read and write to this directory.
@result A new cache object, or nil if an error occurs.
*/
- (nullable instancetype)initWithName:(NSString *)name;
/**
Create a new instance with the specified path.
Multiple instances with the same name will make the cache unstable.
@param path Full path of a directory in which the cache will write data.
Once initialized you should not read and write to this directory.
@result A new cache object, or nil if an error occurs.
*/
- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
/**
Convenience Initializers
Create a new instance with the specified name.
Multiple instances with the same name will make the cache unstable.
@param name The name of the cache. It will create a dictionary with the name in
the app's caches dictionary for disk cache. Once initialized you should not
read and write to this directory.
@result A new cache object, or nil if an error occurs.
*/
+ (nullable instancetype)cacheWithName:(NSString *)name;
/**
Convenience Initializers
Create a new instance with the specified path.
Multiple instances with the same name will make the cache unstable.
@param path Full path of a directory in which the cache will write data.
Once initialized you should not read and write to this directory.
@result A new cache object, or nil if an error occurs.
*/
+ (nullable instancetype)cacheWithPath:(NSString *)path;
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
#pragma mark - Access Methods
///=============================================================================
/// @name Access Methods
///=============================================================================
/**
Returns a boolean value that indicates whether a given key is in cache.
This method may blocks the calling thread until file read finished.
@param key A string identifying the value. If nil, just return NO.
@return Whether the key is in cache.
*/
- (BOOL)containsObjectForKey:(NSString *)key;
/**
Returns a boolean value with the block that indicates whether a given key is in cache.
This method returns immediately and invoke the passed block in background queue
when the operation finished.
@param key A string identifying the value. If nil, just return NO.
@param block A block which will be invoked in background queue when finished.
*/
- (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block;
/**
Returns the value associated with a given key.
This method may blocks the calling thread until file read finished.
@param key A string identifying the value. If nil, just return nil.
@return The value associated with key, or nil if no value is associated with key.
*/
- (nullable id<NSCoding>)objectForKey:(NSString *)key;
/**
Returns the value associated with a given key.
This method returns immediately and invoke the passed block in background queue
when the operation finished.
@param key A string identifying the value. If nil, just return nil.
@param block A block which will be invoked in background queue when finished.
*/
- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id<NSCoding> object))block;
/**
Sets the value of the specified key in the cache.
This method may blocks the calling thread until file write finished.
@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.
@param key The key with which to associate the value. If nil, this method has no effect.
*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key;
/**
Sets the value of the specified key in the cache.
This method returns immediately and invoke the passed block in background queue
when the operation finished.
@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.
@param block A block which will be invoked in background queue when finished.
*/
- (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block;
/**
Removes the value of the specified key in the cache.
This method may blocks the calling thread until file delete finished.
@param key The key identifying the value to be removed. If nil, this method has no effect.
*/
- (void)removeObjectForKey:(NSString *)key;
/**
Removes the value of the specified key in the cache.
This method returns immediately and invoke the passed block in background queue
when the operation finished.
@param key The key identifying the value to be removed. If nil, this method has no effect.
@param block A block which will be invoked in background queue when finished.
*/
- (void)removeObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key))block;
/**
Empties the cache.
This method may blocks the calling thread until file delete finished.
*/
- (void)removeAllObjects;
/**
Empties the cache.
This method returns immediately and invoke the passed block in background queue
when the operation finished.
@param block A block which will be invoked in background queue when finished.
*/
- (void)removeAllObjectsWithBlock:(void(^)(void))block;
/**
Empties the cache with block.
This method returns immediately and executes the clear operation with block in background.
@warning You should not send message to this instance in these blocks.
@param progress This block will be invoked during removing, pass nil to ignore.
@param end This block will be invoked at the end, pass nil to ignore.
*/
- (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress
endBlock:(nullable void(^)(BOOL error))end;
@end
NS_ASSUME_NONNULL_END
//
// YYCache.m
// YYCache <https://github.com/ibireme/YYCache>
//
// Created by ibireme on 15/2/13.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "YYCache.h"
#import "YYMemoryCache.h"
#import "YYDiskCache.h"
@implementation YYCache
- (instancetype) init {
NSLog(@"Use \"initWithName\" or \"initWithPath\" to create YYCache instance.");
return [self initWithPath:@""];
}
- (instancetype)initWithName:(NSString *)name {
if (name.length == 0) return nil;
NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
NSString *path = [cacheFolder stringByAppendingPathComponent:name];
return [self initWithPath:path];
}
- (instancetype)initWithPath:(NSString *)path {
if (path.length == 0) return nil;
YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path];
if (!diskCache) return nil;
NSString *name = [path lastPathComponent];
YYMemoryCache *memoryCache = [YYMemoryCache new];
memoryCache.name = name;
self = [super init];
_name = name;
_diskCache = diskCache;
_memoryCache = memoryCache;
return self;
}
+ (instancetype)cacheWithName:(NSString *)name {
return [[self alloc] initWithName:name];
}
+ (instancetype)cacheWithPath:(NSString *)path {
return [[self alloc] initWithPath:path];
}
- (BOOL)containsObjectForKey:(NSString *)key {
return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key];
}
- (void)containsObjectForKey:(NSString *)key withBlock:(void (^)(NSString *key, BOOL contains))block {
if (!block) return;
if ([_memoryCache containsObjectForKey:key]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
block(key, YES);
});
} else {
[_diskCache containsObjectForKey:key withBlock:block];
}
}
- (id<NSCoding>)objectForKey:(NSString *)key {
id<NSCoding> object = [_memoryCache objectForKey:key];
if (!object) {
object = [_diskCache objectForKey:key];
if (object) {
[_memoryCache setObject:object forKey:key];
}
}
return object;
}
- (void)objectForKey:(NSString *)key withBlock:(void (^)(NSString *key, id<NSCoding> object))block {
if (!block) return;
id<NSCoding> object = [_memoryCache objectForKey:key];
if (object) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
block(key, object);
});
} else {
[_diskCache objectForKey:key withBlock:^(NSString *key, id<NSCoding> object) {
if (object && ![_memoryCache objectForKey:key]) {
[_memoryCache setObject:object forKey:key];
}
block(key, object);
}];
}
}
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key {
[_memoryCache setObject:object forKey:key];
[_diskCache setObject:object forKey:key];
}
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key withBlock:(void (^)(void))block {
[_memoryCache setObject:object forKey:key];
[_diskCache setObject:object forKey:key withBlock:block];
}
- (void)removeObjectForKey:(NSString *)key {
[_memoryCache removeObjectForKey:key];
[_diskCache removeObjectForKey:key];
}
- (void)removeObjectForKey:(NSString *)key withBlock:(void (^)(NSString *key))block {
[_memoryCache removeObjectForKey:key];
[_diskCache removeObjectForKey:key withBlock:block];
}
- (void)removeAllObjects {
[_memoryCache removeAllObjects];
[_diskCache removeAllObjects];
}
- (void)removeAllObjectsWithBlock:(void(^)(void))block {
[_memoryCache removeAllObjects];
[_diskCache removeAllObjectsWithBlock:block];
}
- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress
endBlock:(void(^)(BOOL error))end {
[_memoryCache removeAllObjects];
[_diskCache removeAllObjectsWithProgressBlock:progress endBlock:end];
}
- (NSString *)description {
if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _name];
else return [NSString stringWithFormat:@"<%@: %p>", self.class, self];
}
@end
//
// YYMemoryCache.h
// YYCache <https://github.com/ibireme/YYCache>
//
// Created by ibireme on 15/2/7.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
YYMemoryCache is a fast in-memory cache that stores key-value pairs.
In contrast to NSDictionary, keys are retained and not copied.
The API and performance is similar to `NSCache`, all methods are thread-safe.
YYMemoryCache objects differ from NSCache in a few ways:
* It uses LRU (least-recently-used) to remove objects; NSCache's eviction method
is non-deterministic.
* It can be controlled by cost, count and age; NSCache's limits are imprecise.
* It can be configured to automatically evict objects when receive memory
warning or app enter background.
The time of `Access Methods` in YYMemoryCache is typically in constant time (O(1)).
*/
@interface YYMemoryCache : NSObject
#pragma mark - Attribute
///=============================================================================
/// @name Attribute
///=============================================================================
/** The name of the cache. Default is nil. */
@property (nullable, copy) NSString *name;
/** The number of objects in the cache (read-only) */
@property (readonly) NSUInteger totalCount;
/** The total cost of objects in the cache (read-only). */
@property (readonly) NSUInteger totalCost;
#pragma mark - Limit
///=============================================================================
/// @name Limit
///=============================================================================
/**
The maximum number of objects the cache should hold.
@discussion The default value is NSUIntegerMax, which means no limit.
This is not a strict limit—if the cache goes over the limit, some objects in the
cache could be evicted later in backgound thread.
*/
@property NSUInteger countLimit;
/**
The maximum total cost that the cache can hold before it starts evicting objects.
@discussion The default value is NSUIntegerMax, which means no limit.
This is not a strict limit—if the cache goes over the limit, some objects in the
cache could be evicted later in backgound thread.
*/
@property NSUInteger costLimit;
/**
The maximum expiry time of objects in cache.
@discussion The default value is DBL_MAX, which means no limit.
This is not a strict limit—if an object goes over the limit, the object could
be evicted later in backgound thread.
*/
@property NSTimeInterval ageLimit;
/**
The auto trim check time interval in seconds. Default is 5.0.
@discussion The cache holds an internal timer to check whether the cache reaches
its limits, and if the limit is reached, it begins to evict objects.
*/
@property NSTimeInterval autoTrimInterval;
/**
If `YES`, the cache will remove all objects when the app receives a memory warning.
The default value is `YES`.
*/
@property BOOL shouldRemoveAllObjectsOnMemoryWarning;
/**
If `YES`, The cache will remove all objects when the app enter background.
The default value is `YES`.
*/
@property BOOL shouldRemoveAllObjectsWhenEnteringBackground;
/**
A block to be executed when the app receives a memory warning.
The default value is nil.
*/
@property (nullable, copy) void(^didReceiveMemoryWarningBlock)(YYMemoryCache *cache);
/**
A block to be executed when the app enter background.
The default value is nil.
*/
@property (nullable, copy) void(^didEnterBackgroundBlock)(YYMemoryCache *cache);
/**
If `YES`, the key-value pair will be released on main thread, otherwise on
background thread. Default is NO.
@discussion You may set this value to `YES` if the key-value object contains
the instance which should be released in main thread (such as UIView/CALayer).
*/
@property BOOL releaseOnMainThread;
/**
If `YES`, the key-value pair will be released asynchronously to avoid blocking
the access methods, otherwise it will be released in the access method
(such as removeObjectForKey:). Default is YES.
*/
@property BOOL releaseAsynchronously;
#pragma mark - Access Methods
///=============================================================================
/// @name Access Methods
///=============================================================================
/**
Returns a Boolean value that indicates whether a given key is in cache.
@param key An object identifying the value. If nil, just return `NO`.
@return Whether the key is in cache.
*/
- (BOOL)containsObjectForKey:(id)key;
/**
Returns the value associated with a given key.
@param key An object identifying the value. If nil, just return nil.
@return The value associated with key, or nil if no value is associated with key.
*/
- (nullable id)objectForKey:(id)key;
/**
Sets the value of the specified key in the cache (0 cost).
@param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`.
@param key The key with which to associate the value. If nil, this method has no effect.
@discussion Unlike an NSMutableDictionary object, a cache does not copy the key
objects that are put into it.
*/
- (void)setObject:(nullable id)object forKey:(id)key;
/**
Sets the value of the specified key in the cache, and associates the key-value
pair with the specified cost.
@param object The object to store in the cache. If nil, it calls `removeObjectForKey`.
@param key The key with which to associate the value. If nil, this method has no effect.
@param cost The cost with which to associate the key-value pair.
@discussion Unlike an NSMutableDictionary object, a cache does not copy the key
objects that are put into it.
*/
- (void)setObject:(nullable id)object forKey:(id)key withCost:(NSUInteger)cost;
/**
Removes the value of the specified key in the cache.
@param key The key identifying the value to be removed. If nil, this method has no effect.
*/
- (void)removeObjectForKey:(id)key;
/**
Empties the cache immediately.
*/
- (void)removeAllObjects;
#pragma mark - Trim
///=============================================================================
/// @name Trim
///=============================================================================
/**
Removes objects from the cache with LRU, until the `totalCount` is below or equal to
the specified value.
@param count The total count allowed to remain after the cache has been trimmed.
*/
- (void)trimToCount:(NSUInteger)count;
/**
Removes objects from the cache with LRU, until the `totalCost` is or equal to
the specified value.
@param cost The total cost allowed to remain after the cache has been trimmed.
*/
- (void)trimToCost:(NSUInteger)cost;
/**
Removes objects from the cache with LRU, until all expiry objects removed by the
specified value.
@param age The maximum age (in seconds) of objects.
*/
- (void)trimToAge:(NSTimeInterval)age;
@end
NS_ASSUME_NONNULL_END
The MIT License (MIT)
Copyright (c) 2015 ibireme <ibireme@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
/* src/webp/config.h. Generated from config.h.in by configure. */
/* src/webp/config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Set to 1 if __builtin_bswap16 is available */
#define HAVE_BUILTIN_BSWAP16 1
/* Set to 1 if __builtin_bswap32 is available */
#define HAVE_BUILTIN_BSWAP32 1
/* Set to 1 if __builtin_bswap64 is available */
#define HAVE_BUILTIN_BSWAP64 1
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <GLUT/glut.h> header file. */
/* #undef HAVE_GLUT_GLUT_H */
/* Define to 1 if you have the <GL/glut.h> header file. */
/* #undef HAVE_GL_GLUT_H */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <OpenGL/glut.h> header file. */
/* #undef HAVE_OPENGL_GLUT_H */
/* Have PTHREAD_PRIO_INHERIT. */
#define HAVE_PTHREAD_PRIO_INHERIT 1
/* Define to 1 if you have the <shlwapi.h> header file. */
/* #undef HAVE_SHLWAPI_H */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <wincodec.h> header file. */
/* #undef HAVE_WINCODEC_H */
/* Define to 1 if you have the <windows.h> header file. */
/* #undef HAVE_WINDOWS_H */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libwebp"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "https://bugs.chromium.org/p/webp"
/* Define to the full name of this package. */
#define PACKAGE_NAME "libwebp"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "libwebp 0.5.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libwebp"
/* Define to the home page for this package. */
#define PACKAGE_URL "http://developers.google.com/speed/webp"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.5.0"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
/* #undef PTHREAD_CREATE_JOINABLE */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.5.0"
/* Enable experimental code */
/* #undef WEBP_EXPERIMENTAL_FEATURES */
/* Define to 1 to force aligned memory operations */
/* #undef WEBP_FORCE_ALIGNED */
/* Set to 1 if AVX2 is supported */
/* #undef WEBP_HAVE_AVX2 */
/* Set to 1 if GIF library is installed */
/* #undef WEBP_HAVE_GIF */
/* Set to 1 if OpenGL is supported */
/* #undef WEBP_HAVE_GL */
/* Set to 1 if JPEG library is installed */
/* #undef WEBP_HAVE_JPEG */
/* Set to 1 if PNG library is installed */
/* #undef WEBP_HAVE_PNG */
/* Set to 1 if SSE2 is supported */
/* #undef WEBP_HAVE_SSE2 */
/* Set to 1 if SSE4.1 is supported */
/* #undef WEBP_HAVE_SSE41 */
/* Set to 1 if TIFF library is installed */
/* #undef WEBP_HAVE_TIFF */
/* Undefine this to disable thread support. */
#define WEBP_USE_THREAD 1
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
#ifndef WEBP_WEBP_EXTRAS_H_
#define WEBP_WEBP_EXTRAS_H_
#include "./types.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "./encode.h"
#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b)
//------------------------------------------------------------------------------
// Returns the version number of the extras library, packed in hexadecimal using
// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507.
WEBP_EXTERN(int) WebPGetExtrasVersion(void);
//------------------------------------------------------------------------------
// Ad-hoc colorspace importers.
// Import luma sample (gray scale image) into 'picture'. The 'picture'
// width and height must be set prior to calling this function.
WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture);
// Import rgb sample in RGB565 packed format into 'picture'. The 'picture'
// width and height must be set prior to calling this function.
WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic);
// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture'
// width and height must be set prior to calling this function.
WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic);
//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBP_WEBP_EXTRAS_H_ */
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Internal header for constants related to WebP file format.
//
// Author: Urvang (urvang@google.com)
#ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_
#define WEBP_WEBP_FORMAT_CONSTANTS_H_
// Create fourcc of the chunk from the chunk tag characters.
#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24)
// VP8 related constants.
#define VP8_SIGNATURE 0x9d012a // Signature in VP8 data.
#define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition
#define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition
#define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data.
// VP8L related constants.
#define VP8L_SIGNATURE_SIZE 1 // VP8L signature size.
#define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte.
#define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store
// width and height.
#define VP8L_VERSION_BITS 3 // 3 bits reserved for version.
#define VP8L_VERSION 0 // version 0
#define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header.
#define MAX_PALETTE_SIZE 256
#define MAX_CACHE_BITS 11
#define HUFFMAN_CODES_PER_META_CODE 5
#define ARGB_BLACK 0xff000000
#define DEFAULT_CODE_LENGTH 8
#define MAX_ALLOWED_CODE_LENGTH 15
#define NUM_LITERAL_CODES 256
#define NUM_LENGTH_CODES 24
#define NUM_DISTANCE_CODES 40
#define CODE_LENGTH_CODES 19
#define MIN_HUFFMAN_BITS 2 // min number of Huffman bits
#define MAX_HUFFMAN_BITS 9 // max number of Huffman bits
#define TRANSFORM_PRESENT 1 // The bit to be written when next data
// to be read is a transform.
#define NUM_TRANSFORMS 4 // Maximum number of allowed transform
// in a bitstream.
typedef enum {
PREDICTOR_TRANSFORM = 0,
CROSS_COLOR_TRANSFORM = 1,
SUBTRACT_GREEN = 2,
COLOR_INDEXING_TRANSFORM = 3
} VP8LImageTransformType;
// Alpha related constants.
#define ALPHA_HEADER_LEN 1
#define ALPHA_NO_COMPRESSION 0
#define ALPHA_LOSSLESS_COMPRESSION 1
#define ALPHA_PREPROCESSED_LEVELS 1
// Mux related constants.
#define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L").
#define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size.
#define CHUNK_HEADER_SIZE 8 // Size of a chunk header.
#define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP").
#define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk.
#define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk.
#define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk.
#define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk.
#define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height.
#define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height.
#define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count
#define MAX_DURATION (1 << 24) // maximum duration
#define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset
// Maximum chunk payload is such that adding the header and padding won't
// overflow a uint32_t.
#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)
#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
// Copyright 2012 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Data-types common to the mux and demux libraries.
//
// Author: Urvang (urvang@google.com)
#ifndef WEBP_WEBP_MUX_TYPES_H_
#define WEBP_WEBP_MUX_TYPES_H_
#include <stdlib.h> // free()
#include <string.h> // memset()
#include "./types.h"
#ifdef __cplusplus
extern "C" {
#endif
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
// the types are left here for reference.
// typedef enum WebPFeatureFlags WebPFeatureFlags;
// typedef enum WebPMuxAnimDispose WebPMuxAnimDispose;
// typedef enum WebPMuxAnimBlend WebPMuxAnimBlend;
typedef struct WebPData WebPData;
// VP8X Feature Flags.
typedef enum WebPFeatureFlags {
FRAGMENTS_FLAG = 0x00000001,
ANIMATION_FLAG = 0x00000002,
XMP_FLAG = 0x00000004,
EXIF_FLAG = 0x00000008,
ALPHA_FLAG = 0x00000010,
ICCP_FLAG = 0x00000020
} WebPFeatureFlags;
// Dispose method (animation only). Indicates how the area used by the current
// frame is to be treated before rendering the next frame on the canvas.
typedef enum WebPMuxAnimDispose {
WEBP_MUX_DISPOSE_NONE, // Do not dispose.
WEBP_MUX_DISPOSE_BACKGROUND // Dispose to background color.
} WebPMuxAnimDispose;
// Blend operation (animation only). Indicates how transparent pixels of the
// current frame are blended with those of the previous canvas.
typedef enum WebPMuxAnimBlend {
WEBP_MUX_BLEND, // Blend.
WEBP_MUX_NO_BLEND // Do not blend.
} WebPMuxAnimBlend;
// Data type used to describe 'raw' data, e.g., chunk data
// (ICC profile, metadata) and WebP compressed image data.
struct WebPData {
const uint8_t* bytes;
size_t size;
};
// Initializes the contents of the 'webp_data' object with default values.
static WEBP_INLINE void WebPDataInit(WebPData* webp_data) {
if (webp_data != NULL) {
memset(webp_data, 0, sizeof(*webp_data));
}
}
// Clears the contents of the 'webp_data' object by calling free(). Does not
// deallocate the object itself.
static WEBP_INLINE void WebPDataClear(WebPData* webp_data) {
if (webp_data != NULL) {
free((void*)webp_data->bytes);
WebPDataInit(webp_data);
}
}
// Allocates necessary storage for 'dst' and copies the contents of 'src'.
// Returns true on success.
static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
if (src == NULL || dst == NULL) return 0;
WebPDataInit(dst);
if (src->bytes != NULL && src->size != 0) {
dst->bytes = (uint8_t*)malloc(src->size);
if (dst->bytes == NULL) return 0;
memcpy((void*)dst->bytes, src->bytes, src->size);
dst->size = src->size;
}
return 1;
}
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* WEBP_WEBP_MUX_TYPES_H_ */
// Copyright 2010 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------
//
// Common types
//
// Author: Skal (pascal.massimino@gmail.com)
#ifndef WEBP_WEBP_TYPES_H_
#define WEBP_WEBP_TYPES_H_
#include <stddef.h> // for size_t
#ifndef _MSC_VER
#include <inttypes.h>
#if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L)
#define WEBP_INLINE inline
#else
#define WEBP_INLINE
#endif
#else
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
typedef long long int int64_t;
#define WEBP_INLINE __forceinline
#endif /* _MSC_VER */
#ifndef WEBP_EXTERN
// This explicitly marks library functions and allows for changing the
// signature for e.g., Windows DLL builds.
# if defined(__GNUC__) && __GNUC__ >= 4
# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type
# else
# define WEBP_EXTERN(type) extern type
# endif /* __GNUC__ >= 4 */
#endif /* WEBP_EXTERN */
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))
#endif /* WEBP_WEBP_TYPES_H_ */
//
// YYAnimatedImageView.h
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 14/10/19.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/**
An image view for displaying animated image.
@discussion It is a fully compatible `UIImageView` subclass.
If the `image` or `highlightedImage` property adopt to the `YYAnimatedImage` protocol,
then it can be used to play the multi-frame animation. The animation can also be
controlled with the UIImageView methods `-startAnimating`, `-stopAnimating` and `-isAnimating`.
This view request the frame data just in time. When the device has enough free memory,
this view may cache some or all future frames in an inner buffer for lower CPU cost.
Buffer size is dynamically adjusted based on the current state of the device memory.
Sample Code:
// ani@3x.gif
YYImage *image = [YYImage imageNamed:@"ani"];
YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image];
[view addSubView:imageView];
*/
@interface YYAnimatedImageView : UIImageView
/**
If the image has more than one frame, set this value to `YES` will automatically
play/stop the animation when the view become visible/invisible.
The default value is `YES`.
*/
@property (nonatomic) BOOL autoPlayAnimatedImage;
/**
Index of the currently displayed frame (index from 0).
Set a new value to this property will cause to display the new frame immediately.
If the new value is invalid, this method has no effect.
You can add an observer to this property to observe the playing status.
*/
@property (nonatomic) NSUInteger currentAnimatedImageIndex;
/**
Whether the image view is playing animation currently.
You can add an observer to this property to observe the playing status.
*/
@property (nonatomic, readonly) BOOL currentIsPlayingAnimation;
/**
The animation timer's runloop mode, default is `NSRunLoopCommonModes`.
Set this property to `NSDefaultRunLoopMode` will make the animation pause during
UIScrollView scrolling.
*/
@property (nonatomic, copy) NSString *runloopMode;
/**
The max size (in bytes) for inner frame buffer size, default is 0 (dynamically).
When the device has enough free memory, this view will request and decode some or
all future frame image into an inner buffer. If this property's value is 0, then
the max buffer size will be dynamically adjusted based on the current state of
the device free memory. Otherwise, the buffer size will be limited by this value.
When receive memory warning or app enter background, the buffer will be released
immediately, and may grow back at the right time.
*/
@property (nonatomic) NSUInteger maxBufferSize;
@end
/**
The YYAnimatedImage protocol declares the required methods for animated image
display with YYAnimatedImageView.
Subclass a UIImage and implement this protocol, so that instances of that class
can be set to YYAnimatedImageView.image or YYAnimatedImageView.highlightedImage
to display animation.
See `YYImage` and `YYFrameImage` for example.
*/
@protocol YYAnimatedImage <NSObject>
@required
/// Total animated frame count.
/// It the frame count is less than 1, then the methods below will be ignored.
- (NSUInteger)animatedImageFrameCount;
/// Animation loop count, 0 means infinite looping.
- (NSUInteger)animatedImageLoopCount;
/// Bytes per frame (in memory). It may used to optimize memory buffer size.
- (NSUInteger)animatedImageBytesPerFrame;
/// Returns the frame image from a specified index.
/// This method may be called on background thread.
/// @param index Frame index (zero based).
- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index;
/// Returns the frames's duration from a specified index.
/// @param index Frame index (zero based).
- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index;
@optional
/// A rectangle in image coordinates defining the subrectangle of the image that
/// will be displayed. The rectangle should not outside the image's bounds.
/// It may used to display sprite animation with a single image (sprite sheet).
- (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index;
@end
NS_ASSUME_NONNULL_END
//
// YYFrameImage.h
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 14/12/9.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#if __has_include(<YYImage/YYImage.h>)
#import <YYImage/YYAnimatedImageView.h>
#elif __has_include(<YYWebImage/YYImage.h>)
#import <YYWebImage/YYAnimatedImageView.h>
#else
#import "YYAnimatedImageView.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
An image to display frame-based animation.
@discussion It is a fully compatible `UIImage` subclass.
It only support system image format such as png and jpeg.
The animation can be played by YYAnimatedImageView.
Sample Code:
NSArray *paths = @[@"/ani/frame1.png", @"/ani/frame2.png", @"/ani/frame3.png"];
NSArray *times = @[@0.1, @0.2, @0.1];
YYFrameImage *image = [YYFrameImage alloc] initWithImagePaths:paths frameDurations:times repeats:YES];
YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image];
[view addSubView:imageView];
*/
@interface YYFrameImage : UIImage <YYAnimatedImage>
/**
Create a frame animated image from files.
@param paths An array of NSString objects, contains the full or
partial path to each image file.
e.g. @[@"/ani/1.png",@"/ani/2.png",@"/ani/3.png"]
@param oneFrameDuration The duration (in seconds) per frame.
@param loopCount The animation loop count, 0 means infinite.
@return An initialized YYFrameImage object, or nil when an error occurs.
*/
- (nullable instancetype)initWithImagePaths:(NSArray<NSString *> *)paths
oneFrameDuration:(NSTimeInterval)oneFrameDuration
loopCount:(NSUInteger)loopCount;
/**
Create a frame animated image from files.
@param paths An array of NSString objects, contains the full or
partial path to each image file.
e.g. @[@"/ani/frame1.png",@"/ani/frame2.png",@"/ani/frame3.png"]
@param frameDurations An array of NSNumber objects, contains the duration (in seconds) per frame.
e.g. @[@0.1, @0.2, @0.3];
@param loopCount The animation loop count, 0 means infinite.
@return An initialized YYFrameImage object, or nil when an error occurs.
*/
- (nullable instancetype)initWithImagePaths:(NSArray<NSString *> *)paths
frameDurations:(NSArray<NSNumber *> *)frameDurations
loopCount:(NSUInteger)loopCount;
/**
Create a frame animated image from an array of data.
@param dataArray An array of NSData objects.
@param oneFrameDuration The duration (in seconds) per frame.
@param loopCount The animation loop count, 0 means infinite.
@return An initialized YYFrameImage object, or nil when an error occurs.
*/
- (nullable instancetype)initWithImageDataArray:(NSArray<NSData *> *)dataArray
oneFrameDuration:(NSTimeInterval)oneFrameDuration
loopCount:(NSUInteger)loopCount;
/**
Create a frame animated image from an array of data.
@param dataArray An array of NSData objects.
@param frameDurations An array of NSNumber objects, contains the duration (in seconds) per frame.
e.g. @[@0.1, @0.2, @0.3];
@param loopCount The animation loop count, 0 means infinite.
@return An initialized YYFrameImage object, or nil when an error occurs.
*/
- (nullable instancetype)initWithImageDataArray:(NSArray<NSData *> *)dataArray
frameDurations:(NSArray *)frameDurations
loopCount:(NSUInteger)loopCount;
@end
NS_ASSUME_NONNULL_END
//
// YYFrameImage.m
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 14/12/9.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "YYFrameImage.h"
#import "YYImageCoder.h"
/**
Return the path scale.
e.g.
<table>
<tr><th>Path </th><th>Scale </th></tr>
<tr><td>"icon.png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png" </td><td>2 </td></tr>
<tr><td>"icon@2.5x.png" </td><td>2.5 </td></tr>
<tr><td>"icon@2x" </td><td>1 </td></tr>
<tr><td>"icon@2x..png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png/" </td><td>1 </td></tr>
</table>
*/
static CGFloat _NSStringPathScale(NSString *string) {
if (string.length == 0 || [string hasSuffix:@"/"]) return 1;
NSString *name = string.stringByDeletingPathExtension;
__block CGFloat scale = 1;
NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil];
[pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
if (result.range.location >= 3) {
scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue;
}
}];
return scale;
}
@implementation YYFrameImage {
NSUInteger _loopCount;
NSUInteger _oneFrameBytes;
NSArray *_imagePaths;
NSArray *_imageDatas;
NSArray *_frameDurations;
}
- (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount {
NSMutableArray *durations = [NSMutableArray new];
for (int i = 0, max = (int)paths.count; i < max; i++) {
[durations addObject:@(oneFrameDuration)];
}
return [self initWithImagePaths:paths frameDurations:durations loopCount:loopCount];
}
- (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount {
if (paths.count == 0) return nil;
if (paths.count != frameDurations.count) return nil;
NSString *firstPath = paths[0];
NSData *firstData = [NSData dataWithContentsOfFile:firstPath];
CGFloat scale = _NSStringPathScale(firstPath);
UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded];
self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp];
if (!self) return nil;
long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage);
_oneFrameBytes = (NSUInteger)frameByte;
_imagePaths = paths.copy;
_frameDurations = frameDurations.copy;
_loopCount = loopCount;
return self;
}
- (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount {
NSMutableArray *durations = [NSMutableArray new];
for (int i = 0, max = (int)dataArray.count; i < max; i++) {
[durations addObject:@(oneFrameDuration)];
}
return [self initWithImageDataArray:dataArray frameDurations:durations loopCount:loopCount];
}
- (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount {
if (dataArray.count == 0) return nil;
if (dataArray.count != frameDurations.count) return nil;
NSData *firstData = dataArray[0];
CGFloat scale = [UIScreen mainScreen].scale;
UIImage *firstCG = [[[UIImage alloc] initWithData:firstData] yy_imageByDecoded];
self = [self initWithCGImage:firstCG.CGImage scale:scale orientation:UIImageOrientationUp];
if (!self) return nil;
long frameByte = CGImageGetBytesPerRow(firstCG.CGImage) * CGImageGetHeight(firstCG.CGImage);
_oneFrameBytes = (NSUInteger)frameByte;
_imageDatas = dataArray.copy;
_frameDurations = frameDurations.copy;
_loopCount = loopCount;
return self;
}
#pragma mark - YYAnimtedImage
- (NSUInteger)animatedImageFrameCount {
if (_imagePaths) {
return _imagePaths.count;
} else if (_imageDatas) {
return _imageDatas.count;
} else {
return 1;
}
}
- (NSUInteger)animatedImageLoopCount {
return _loopCount;
}
- (NSUInteger)animatedImageBytesPerFrame {
return _oneFrameBytes;
}
- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {
if (_imagePaths) {
if (index >= _imagePaths.count) return nil;
NSString *path = _imagePaths[index];
CGFloat scale = _NSStringPathScale(path);
NSData *data = [NSData dataWithContentsOfFile:path];
return [[UIImage imageWithData:data scale:scale] yy_imageByDecoded];
} else if (_imageDatas) {
if (index >= _imageDatas.count) return nil;
NSData *data = _imageDatas[index];
return [[UIImage imageWithData:data scale:[UIScreen mainScreen].scale] yy_imageByDecoded];
} else {
return index == 0 ? self : nil;
}
}
- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {
if (index >= _frameDurations.count) return 0;
NSNumber *num = _frameDurations[index];
return [num doubleValue];
}
@end
//
// YYImage.h
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 14/10/20.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#if __has_include(<YYImage/YYImage.h>)
FOUNDATION_EXPORT double YYImageVersionNumber;
FOUNDATION_EXPORT const unsigned char YYImageVersionString[];
#import <YYImage/YYFrameImage.h>
#import <YYImage/YYSpriteSheetImage.h>
#import <YYImage/YYImageCoder.h>
#import <YYImage/YYAnimatedImageView.h>
#elif __has_include(<YYWebImage/YYImage.h>)
#import <YYWebImage/YYFrameImage.h>
#import <YYWebImage/YYSpriteSheetImage.h>
#import <YYWebImage/YYImageCoder.h>
#import <YYWebImage/YYAnimatedImageView.h>
#else
#import "YYFrameImage.h"
#import "YYSpriteSheetImage.h"
#import "YYImageCoder.h"
#import "YYAnimatedImageView.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
A YYImage object is a high-level way to display animated image data.
@discussion It is a fully compatible `UIImage` subclass. It extends the UIImage
to support animated WebP, APNG and GIF format image data decoding. It also
support NSCoding protocol to archive and unarchive multi-frame image data.
If the image is created from multi-frame image data, and you want to play the
animation, try replace UIImageView with `YYAnimatedImageView`.
Sample Code:
// animation@3x.webp
YYImage *image = [YYImage imageNamed:@"animation.webp"];
YYAnimatedImageView *imageView = [YYAnimatedImageView alloc] initWithImage:image];
[view addSubView:imageView];
*/
@interface YYImage : UIImage <YYAnimatedImage>
+ (nullable YYImage *)imageNamed:(NSString *)name; // no cache!
+ (nullable YYImage *)imageWithContentsOfFile:(NSString *)path;
+ (nullable YYImage *)imageWithData:(NSData *)data;
+ (nullable YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;
/**
If the image is created from data or file, then the value indicates the data type.
*/
@property (nonatomic, readonly) YYImageType animatedImageType;
/**
If the image is created from animated image data (multi-frame GIF/APNG/WebP),
this property stores the original image data.
*/
@property (nullable, nonatomic, readonly) NSData *animatedImageData;
/**
The total memory usage (in bytes) if all frame images was loaded into memory.
The value is 0 if the image is not created from a multi-frame image data.
*/
@property (nonatomic, readonly) NSUInteger animatedImageMemorySize;
/**
Preload all frame image to memory.
@discussion Set this property to `YES` will block the calling thread to decode
all animation frame image to memory, set to `NO` will release the preloaded frames.
If the image is shared by lots of image views (such as emoticon), preload all
frames will reduce the CPU cost.
See `animatedImageMemorySize` for memory cost.
*/
@property (nonatomic) BOOL preloadAllAnimatedImageFrames;
@end
NS_ASSUME_NONNULL_END
//
// YYImage.m
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 14/10/20.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "YYImage.h"
/**
An array of NSNumber objects, shows the best order for path scale search.
e.g. iPhone3GS:@[@1,@2,@3] iPhone5:@[@2,@3,@1] iPhone6 Plus:@[@3,@2,@1]
*/
static NSArray *_NSBundlePreferredScales() {
static NSArray *scales;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
CGFloat screenScale = [UIScreen mainScreen].scale;
if (screenScale <= 1) {
scales = @[@1,@2,@3];
} else if (screenScale <= 2) {
scales = @[@2,@3,@1];
} else {
scales = @[@3,@2,@1];
}
});
return scales;
}
/**
Add scale modifier to the file name (without path extension),
From @"name" to @"name@2x".
e.g.
<table>
<tr><th>Before </th><th>After(scale:2)</th></tr>
<tr><td>"icon" </td><td>"icon@2x" </td></tr>
<tr><td>"icon " </td><td>"icon @2x" </td></tr>
<tr><td>"icon.top" </td><td>"icon.top@2x" </td></tr>
<tr><td>"/p/name" </td><td>"/p/name@2x" </td></tr>
<tr><td>"/path/" </td><td>"/path/" </td></tr>
</table>
@param scale Resource scale.
@return String by add scale modifier, or just return if it's not end with file name.
*/
static NSString *_NSStringByAppendingNameScale(NSString *string, CGFloat scale) {
if (!string) return nil;
if (fabs(scale - 1) <= __FLT_EPSILON__ || string.length == 0 || [string hasSuffix:@"/"]) return string.copy;
return [string stringByAppendingFormat:@"@%@x", @(scale)];
}
/**
Return the path scale.
e.g.
<table>
<tr><th>Path </th><th>Scale </th></tr>
<tr><td>"icon.png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png" </td><td>2 </td></tr>
<tr><td>"icon@2.5x.png" </td><td>2.5 </td></tr>
<tr><td>"icon@2x" </td><td>1 </td></tr>
<tr><td>"icon@2x..png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png/" </td><td>1 </td></tr>
</table>
*/
static CGFloat _NSStringPathScale(NSString *string) {
if (string.length == 0 || [string hasSuffix:@"/"]) return 1;
NSString *name = string.stringByDeletingPathExtension;
__block CGFloat scale = 1;
NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:@"@[0-9]+\\.?[0-9]*x$" options:NSRegularExpressionAnchorsMatchLines error:nil];
[pattern enumerateMatchesInString:name options:kNilOptions range:NSMakeRange(0, name.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
if (result.range.location >= 3) {
scale = [string substringWithRange:NSMakeRange(result.range.location + 1, result.range.length - 2)].doubleValue;
}
}];
return scale;
}
@implementation YYImage {
YYImageDecoder *_decoder;
NSArray *_preloadedFrames;
dispatch_semaphore_t _preloadedLock;
NSUInteger _bytesPerFrame;
}
+ (YYImage *)imageNamed:(NSString *)name {
if (name.length == 0) return nil;
if ([name hasSuffix:@"/"]) return nil;
NSString *res = name.stringByDeletingPathExtension;
NSString *ext = name.pathExtension;
NSString *path = nil;
CGFloat scale = 1;
// If no extension, guess by system supported (same as UIImage).
NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp", @"apng"];
NSArray *scales = _NSBundlePreferredScales();
for (int s = 0; s < scales.count; s++) {
scale = ((NSNumber *)scales[s]).floatValue;
NSString *scaledName = _NSStringByAppendingNameScale(res, scale);
for (NSString *e in exts) {
path = [[NSBundle mainBundle] pathForResource:scaledName ofType:e];
if (path) break;
}
if (path) break;
}
if (path.length == 0) return nil;
NSData *data = [NSData dataWithContentsOfFile:path];
if (data.length == 0) return nil;
return [[self alloc] initWithData:data scale:scale];
}
+ (YYImage *)imageWithContentsOfFile:(NSString *)path {
return [[self alloc] initWithContentsOfFile:path];
}
+ (YYImage *)imageWithData:(NSData *)data {
return [[self alloc] initWithData:data];
}
+ (YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale {
return [[self alloc] initWithData:data scale:scale];
}
- (instancetype)initWithContentsOfFile:(NSString *)path {
NSData *data = [NSData dataWithContentsOfFile:path];
return [self initWithData:data scale:_NSStringPathScale(path)];
}
- (instancetype)initWithData:(NSData *)data {
return [self initWithData:data scale:1];
}
- (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale {
if (data.length == 0) return nil;
if (scale <= 0) scale = [UIScreen mainScreen].scale;
_preloadedLock = dispatch_semaphore_create(1);
@autoreleasepool {
YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale];
YYImageFrame *frame = [decoder frameAtIndex:0 decodeForDisplay:YES];
UIImage *image = frame.image;
if (!image) return nil;
self = [self initWithCGImage:image.CGImage scale:decoder.scale orientation:image.imageOrientation];
if (!self) return nil;
_animatedImageType = decoder.type;
if (decoder.frameCount > 1) {
_decoder = decoder;
_bytesPerFrame = CGImageGetBytesPerRow(image.CGImage) * CGImageGetHeight(image.CGImage);
_animatedImageMemorySize = _bytesPerFrame * decoder.frameCount;
}
self.yy_isDecodedForDisplay = YES;
}
return self;
}
- (NSData *)animatedImageData {
return _decoder.data;
}
- (void)setPreloadAllAnimatedImageFrames:(BOOL)preloadAllAnimatedImageFrames {
if (_preloadAllAnimatedImageFrames != preloadAllAnimatedImageFrames) {
if (preloadAllAnimatedImageFrames && _decoder.frameCount > 0) {
NSMutableArray *frames = [NSMutableArray new];
for (NSUInteger i = 0, max = _decoder.frameCount; i < max; i++) {
UIImage *img = [self animatedImageFrameAtIndex:i];
if (img) {
[frames addObject:img];
} else {
[frames addObject:[NSNull null]];
}
}
dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER);
_preloadedFrames = frames;
dispatch_semaphore_signal(_preloadedLock);
} else {
dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER);
_preloadedFrames = nil;
dispatch_semaphore_signal(_preloadedLock);
}
}
}
#pragma mark - protocol NSCoding
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
NSNumber *scale = [aDecoder decodeObjectForKey:@"YYImageScale"];
NSData *data = [aDecoder decodeObjectForKey:@"YYImageData"];
if (data.length) {
self = [self initWithData:data scale:scale.doubleValue];
} else {
self = [super initWithCoder:aDecoder];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
if (_decoder.data.length) {
[aCoder encodeObject:@(self.scale) forKey:@"YYImageScale"];
[aCoder encodeObject:_decoder.data forKey:@"YYImageData"];
} else {
[super encodeWithCoder:aCoder]; // Apple use UIImagePNGRepresentation() to encode UIImage.
}
}
#pragma mark - protocol YYAnimatedImage
- (NSUInteger)animatedImageFrameCount {
return _decoder.frameCount;
}
- (NSUInteger)animatedImageLoopCount {
return _decoder.loopCount;
}
- (NSUInteger)animatedImageBytesPerFrame {
return _bytesPerFrame;
}
- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {
if (index >= _decoder.frameCount) return nil;
dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER);
UIImage *image = _preloadedFrames[index];
dispatch_semaphore_signal(_preloadedLock);
if (image) return image == (id)[NSNull null] ? nil : image;
return [_decoder frameAtIndex:index decodeForDisplay:YES].image;
}
- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {
NSTimeInterval duration = [_decoder frameDurationAtIndex:index];
/*
http://opensource.apple.com/source/WebCore/WebCore-7600.1.25/platform/graphics/cg/ImageSourceCG.cpp
Many annoying ads specify a 0 duration to make an image flash as quickly as
possible. We follow Safari and Firefox's behavior and use a duration of 100 ms
for any frames that specify a duration of <= 10 ms.
See <rdar://problem/7689300> and <http://webkit.org/b/36082> for more information.
See also: http://nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser.
*/
if (duration < 0.011f) return 0.100f;
return duration;
}
@end
此文件的差异太大,无法显示。
//
// YYSpriteImage.h
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 15/4/21.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#if __has_include(<YYImage/YYImage.h>)
#import <YYImage/YYAnimatedImageView.h>
#elif __has_include(<YYWebImage/YYImage.h>)
#import <YYWebImage/YYAnimatedImageView.h>
#else
#import "YYAnimatedImageView.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
An image to display sprite sheet animation.
@discussion It is a fully compatible `UIImage` subclass.
The animation can be played by YYAnimatedImageView.
Sample Code:
// 8 * 12 sprites in a single sheet image
UIImage *spriteSheet = [UIImage imageNamed:@"sprite-sheet"];
NSMutableArray *contentRects = [NSMutableArray new];
NSMutableArray *durations = [NSMutableArray new];
for (int j = 0; j < 12; j++) {
for (int i = 0; i < 8; i++) {
CGRect rect;
rect.size = CGSizeMake(img.size.width / 8, img.size.height / 12);
rect.origin.x = img.size.width / 8 * i;
rect.origin.y = img.size.height / 12 * j;
[contentRects addObject:[NSValue valueWithCGRect:rect]];
[durations addObject:@(1 / 60.0)];
}
}
YYSpriteSheetImage *sprite;
sprite = [[YYSpriteSheetImage alloc] initWithSpriteSheetImage:img
contentRects:contentRects
frameDurations:durations
loopCount:0];
YYAnimatedImageView *imgView = [YYAnimatedImageView new];
imgView.size = CGSizeMake(img.size.width / 8, img.size.height / 12);
imgView.image = sprite;
@discussion It can also be used to display single frame in sprite sheet image.
Sample Code:
YYSpriteSheetImage *sheet = ...;
UIImageView *imageView = ...;
imageView.image = sheet;
imageView.layer.contentsRect = [sheet contentsRectForCALayerAtIndex:6];
*/
@interface YYSpriteSheetImage : UIImage <YYAnimatedImage>
/**
Creates and returns an image object.
@param image The sprite sheet image (contains all frames).
@param contentRects The sprite sheet image frame rects in the image coordinates.
The rectangle should not outside the image's bounds. The objects in this array
should be created with [NSValue valueWithCGRect:].
@param frameDurations The sprite sheet image frame's durations in seconds.
The objects in this array should be NSNumber.
@param loopCount Animation loop count, 0 means infinite looping.
@return An image object, or nil if an error occurs.
*/
- (nullable instancetype)initWithSpriteSheetImage:(UIImage *)image
contentRects:(NSArray<NSValue *> *)contentRects
frameDurations:(NSArray<NSNumber *> *)frameDurations
loopCount:(NSUInteger)loopCount;
@property (nonatomic, readonly) NSArray<NSValue *> *contentRects;
@property (nonatomic, readonly) NSArray<NSValue *> *frameDurations;
@property (nonatomic, readonly) NSUInteger loopCount;
/**
Get the contents rect for CALayer.
See "contentsRect" property in CALayer for more information.
@param index Index of frame.
@return Contents Rect.
*/
- (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index;
@end
NS_ASSUME_NONNULL_END
//
// YYSpriteImage.m
// YYImage <https://github.com/ibireme/YYImage>
//
// Created by ibireme on 15/4/21.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "YYSpriteSheetImage.h"
@implementation YYSpriteSheetImage
- (instancetype)initWithSpriteSheetImage:(UIImage *)image
contentRects:(NSArray *)contentRects
frameDurations:(NSArray *)frameDurations
loopCount:(NSUInteger)loopCount {
if (!image.CGImage) return nil;
if (contentRects.count < 1 || frameDurations.count < 1) return nil;
if (contentRects.count != frameDurations.count) return nil;
self = [super initWithCGImage:image.CGImage scale:image.scale orientation:image.imageOrientation];
if (!self) return nil;
_contentRects = contentRects.copy;
_frameDurations = frameDurations.copy;
_loopCount = loopCount;
return self;
}
- (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index {
CGRect layerRect = CGRectMake(0, 0, 1, 1);
if (index >= _contentRects.count) return layerRect;
CGSize imageSize = self.size;
CGRect rect = [self animatedImageContentsRectAtIndex:index];
if (imageSize.width > 0.01 && imageSize.height > 0.01) {
layerRect.origin.x = rect.origin.x / imageSize.width;
layerRect.origin.y = rect.origin.y / imageSize.height;
layerRect.size.width = rect.size.width / imageSize.width;
layerRect.size.height = rect.size.height / imageSize.height;
layerRect = CGRectIntersection(layerRect, CGRectMake(0, 0, 1, 1));
if (CGRectIsNull(layerRect) || CGRectIsEmpty(layerRect)) {
layerRect = CGRectMake(0, 0, 1, 1);
}
}
return layerRect;
}
#pragma mark @protocol YYAnimatedImage
- (NSUInteger)animatedImageFrameCount {
return _contentRects.count;
}
- (NSUInteger)animatedImageLoopCount {
return _loopCount;
}
- (NSUInteger)animatedImageBytesPerFrame {
return 0;
}
- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {
return self;
}
- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {
if (index >= _frameDurations.count) return 0;
return ((NSNumber *)_frameDurations[index]).doubleValue;
}
- (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index {
if (index >= _contentRects.count) return CGRectZero;
return ((NSValue *)_contentRects[index]).CGRectValue;
}
@end
The MIT License (MIT)
Copyright (c) 2015 ibireme <ibireme@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
//
// CALayer+YYWebImage.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#if __has_include(<YYWebImage/YYWebImage.h>)
#import <YYWebImage/YYWebImageManager.h>
#else
#import "YYWebImageManager.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
Web image methods for CALayer.
It will set image to layer.contents.
*/
@interface CALayer (YYWebImage)
#pragma mark - image
/**
Current image URL.
@discussion Set a new value to this property will cancel the previous request
operation and create a new request operation to fetch image. Set nil to clear
the image and image URL.
*/
@property (nullable, nonatomic, strong) NSURL *yy_imageURL;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param options The options to use when request the image.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder he image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param manager The manager to create image request operation.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(nullable YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Cancel the current image request.
*/
- (void)yy_cancelCurrentImageRequest;
@end
NS_ASSUME_NONNULL_END
//
// CALayer+YYWebImage.m
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "CALayer+YYWebImage.h"
#import "YYWebImageOperation.h"
#import "_YYWebImageSetter.h"
#import <objc/runtime.h>
// Dummy class for category
@interface CALayer_YYWebImage : NSObject @end
@implementation CALayer_YYWebImage @end
static int _YYWebImageSetterKey;
@implementation CALayer (YYWebImage)
- (NSURL *)yy_imageURL {
_YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey);
return setter.imageURL;
}
- (void)setYy_imageURL:(NSURL *)imageURL {
[self yy_setImageWithURL:imageURL
placeholder:nil
options:kNilOptions
manager:nil
progress:nil
transform:nil
completion:nil];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder {
[self yy_setImageWithURL:imageURL
placeholder:placeholder
options:kNilOptions
manager:nil
progress:nil
transform:nil
completion:nil];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options {
[self yy_setImageWithURL:imageURL
placeholder:nil
options:options
manager:nil
progress:nil
transform:nil
completion:nil];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL
placeholder:(UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(YYWebImageCompletionBlock)completion {
[self yy_setImageWithURL:imageURL
placeholder:placeholder
options:options
manager:nil
progress:nil
transform:nil
completion:completion];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL
placeholder:(UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(YYWebImageProgressBlock)progress
transform:(YYWebImageTransformBlock)transform
completion:(YYWebImageCompletionBlock)completion {
[self yy_setImageWithURL:imageURL
placeholder:placeholder
options:options
manager:nil
progress:progress
transform:transform
completion:completion];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL
placeholder:(UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(YYWebImageManager *)manager
progress:(YYWebImageProgressBlock)progress
transform:(YYWebImageTransformBlock)transform
completion:(YYWebImageCompletionBlock)completion {
if ([imageURL isKindOfClass:[NSString class]]) imageURL = [NSURL URLWithString:(id)imageURL];
manager = manager ? manager : [YYWebImageManager sharedManager];
_YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey);
if (!setter) {
setter = [_YYWebImageSetter new];
objc_setAssociatedObject(self, &_YYWebImageSetterKey, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
int32_t sentinel = [setter cancelWithNewURL:imageURL];
_yy_dispatch_sync_on_main_queue(^{
if ((options & YYWebImageOptionSetImageWithFadeAnimation) &&
!(options & YYWebImageOptionAvoidSetImage)) {
[self removeAnimationForKey:_YYWebImageFadeAnimationKey];
}
if (!imageURL) {
if (!(options & YYWebImageOptionIgnorePlaceHolder)) {
self.contents = (id)placeholder.CGImage;
}
return;
}
// get the image from memory as quickly as possible
UIImage *imageFromMemory = nil;
if (manager.cache &&
!(options & YYWebImageOptionUseNSURLCache) &&
!(options & YYWebImageOptionRefreshImageCache)) {
imageFromMemory = [manager.cache getImageForKey:[manager cacheKeyForURL:imageURL] withType:YYImageCacheTypeMemory];
}
if (imageFromMemory) {
if (!(options & YYWebImageOptionAvoidSetImage)) {
self.contents = (id)imageFromMemory.CGImage;
}
if(completion) completion(imageFromMemory, imageURL, YYWebImageFromMemoryCacheFast, YYWebImageStageFinished, nil);
return;
}
if (!(options & YYWebImageOptionIgnorePlaceHolder)) {
self.contents = (id)placeholder.CGImage;
}
__weak typeof(self) _self = self;
dispatch_async([_YYWebImageSetter setterQueue], ^{
YYWebImageProgressBlock _progress = nil;
if (progress) _progress = ^(NSInteger receivedSize, NSInteger expectedSize) {
dispatch_async(dispatch_get_main_queue(), ^{
progress(receivedSize, expectedSize);
});
};
__block int32_t newSentinel = 0;
__block __weak typeof(setter) weakSetter = nil;
YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
__strong typeof(_self) self = _self;
BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
BOOL showFade = (options & YYWebImageOptionSetImageWithFadeAnimation);
dispatch_async(dispatch_get_main_queue(), ^{
BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
if (setImage && self && !sentinelChanged) {
if (showFade) {
CATransition *transition = [CATransition animation];
transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self addAnimation:transition forKey:_YYWebImageFadeAnimationKey];
}
self.contents = (id)image.CGImage;
}
if (completion) {
if (sentinelChanged) {
completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
} else {
completion(image, url, from, stage, error);
}
}
});
};
newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
weakSetter = setter;
});
});
}
- (void)yy_cancelCurrentImageRequest {
_YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey);
if (setter) [setter cancel];
}
@end
//
// MKAnnotationView+YYWebImage.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#if __has_include(<YYWebImage/YYWebImage.h>)
#import <YYWebImage/YYWebImageManager.h>
#else
#import "YYWebImageManager.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
Web image methods for MKAnnotationView.
*/
@interface MKAnnotationView (YYWebImage)
/**
Current image URL.
@discussion Set a new value to this property will cancel the previous request
operation and create a new request operation to fetch image. Set nil to clear
the image and image URL.
*/
@property (nullable, nonatomic, strong) NSURL *yy_imageURL;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param options The options to use when request the image.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder he image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param manager The manager to create image request operation.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(nullable YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Cancel the current image request.
*/
- (void)yy_cancelCurrentImageRequest;
@end
NS_ASSUME_NONNULL_END
//
// MKAnnotationView+YYWebImage.m
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "MKAnnotationView+YYWebImage.h"
#import "YYWebImageOperation.h"
#import "_YYWebImageSetter.h"
#import <objc/runtime.h>
// Dummy class for category
@interface MKAnnotationView_YYWebImage : NSObject @end
@implementation MKAnnotationView_YYWebImage @end
static int _YYWebImageSetterKey;
@implementation MKAnnotationView (YYWebImage)
- (NSURL *)yy_imageURL {
_YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey);
return setter.imageURL;
}
- (void)setYy_imageURL:(NSURL *)imageURL {
[self yy_setImageWithURL:imageURL
placeholder:nil
options:kNilOptions
manager:nil
progress:nil
transform:nil
completion:nil];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder {
[self yy_setImageWithURL:imageURL
placeholder:placeholder
options:kNilOptions
manager:nil
progress:nil
transform:nil
completion:nil];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options {
[self yy_setImageWithURL:imageURL
placeholder:nil
options:options
manager:nil
progress:nil
transform:nil
completion:nil];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL
placeholder:(UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(YYWebImageCompletionBlock)completion {
[self yy_setImageWithURL:imageURL
placeholder:placeholder
options:options
manager:nil
progress:nil
transform:nil
completion:completion];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL
placeholder:(UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(YYWebImageProgressBlock)progress
transform:(YYWebImageTransformBlock)transform
completion:(YYWebImageCompletionBlock)completion {
[self yy_setImageWithURL:imageURL
placeholder:placeholder
options:options
manager:nil
progress:progress
transform:transform
completion:completion];
}
- (void)yy_setImageWithURL:(NSURL *)imageURL
placeholder:(UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(YYWebImageManager *)manager
progress:(YYWebImageProgressBlock)progress
transform:(YYWebImageTransformBlock)transform
completion:(YYWebImageCompletionBlock)completion {
if ([imageURL isKindOfClass:[NSString class]]) imageURL = [NSURL URLWithString:(id)imageURL];
manager = manager ? manager : [YYWebImageManager sharedManager];
_YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey);
if (!setter) {
setter = [_YYWebImageSetter new];
objc_setAssociatedObject(self, &_YYWebImageSetterKey, setter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
int32_t sentinel = [setter cancelWithNewURL:imageURL];
_yy_dispatch_sync_on_main_queue(^{
if ((options & YYWebImageOptionSetImageWithFadeAnimation) &&
!(options & YYWebImageOptionAvoidSetImage)) {
if (!self.highlighted) {
[self.layer removeAnimationForKey:_YYWebImageFadeAnimationKey];
}
}
if (!imageURL) {
if (!(options & YYWebImageOptionIgnorePlaceHolder)) {
self.image = placeholder;
}
return;
}
// get the image from memory as quickly as possible
UIImage *imageFromMemory = nil;
if (manager.cache &&
!(options & YYWebImageOptionUseNSURLCache) &&
!(options & YYWebImageOptionRefreshImageCache)) {
imageFromMemory = [manager.cache getImageForKey:[manager cacheKeyForURL:imageURL] withType:YYImageCacheTypeMemory];
}
if (imageFromMemory) {
if (!(options & YYWebImageOptionAvoidSetImage)) {
self.image = imageFromMemory;
}
if(completion) completion(imageFromMemory, imageURL, YYWebImageFromMemoryCacheFast, YYWebImageStageFinished, nil);
return;
}
if (!(options & YYWebImageOptionIgnorePlaceHolder)) {
self.image = placeholder;
}
__weak typeof(self) _self = self;
dispatch_async([_YYWebImageSetter setterQueue], ^{
YYWebImageProgressBlock _progress = nil;
if (progress) _progress = ^(NSInteger receivedSize, NSInteger expectedSize) {
dispatch_async(dispatch_get_main_queue(), ^{
progress(receivedSize, expectedSize);
});
};
__block int32_t newSentinel = 0;
__block __weak typeof(setter) weakSetter = nil;
YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
__strong typeof(_self) self = _self;
BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted);
dispatch_async(dispatch_get_main_queue(), ^{
BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
if (setImage && self && !sentinelChanged) {
if (showFade) {
CATransition *transition = [CATransition animation];
transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade;
[self.layer addAnimation:transition forKey:_YYWebImageFadeAnimationKey];
}
self.image = image;
}
if (completion) {
if (sentinelChanged) {
completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
} else {
completion(image, url, from, stage, error);
}
}
});
};
newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
weakSetter = setter;
});
});
}
- (void)yy_cancelCurrentImageRequest {
_YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey);
if (setter) [setter cancel];
}
@end
//
// UIButton+YYWebImage.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#if __has_include(<YYWebImage/YYWebImage.h>)
#import <YYWebImage/YYWebImageManager.h>
#else
#import "YYWebImageManager.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
Web image methods for UIButton.
*/
@interface UIButton (YYWebImage)
#pragma mark - image
/**
Current image URL for the specified state.
@return The image URL, or nil.
*/
- (nullable NSURL *)yy_imageURLForState:(UIControlState)state;
/**
Set the button's image with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder;
/**
Set the button's image with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param options The options to use when request the image.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
options:(YYWebImageOptions)options;
/**
Set the button's image with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the button's image with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the button's image with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param manager The manager to create image request operation.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(nullable YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Cancel the current image request for a specified state.
@param state The state that uses the specified image.
*/
- (void)yy_cancelImageRequestForState:(UIControlState)state;
#pragma mark - background image
/**
Current backgroundImage URL for the specified state.
@return The image URL, or nil.
*/
- (nullable NSURL *)yy_backgroundImageURLForState:(UIControlState)state;
/**
Set the button's backgroundImage with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
*/
- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder;
/**
Set the button's backgroundImage with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param options The options to use when request the image.
*/
- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
options:(YYWebImageOptions)options;
/**
Set the button's backgroundImage with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the button's backgroundImage with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the button's backgroundImage with a specified URL for the specified state.
@param imageURL The image url (remote or local file path).
@param state The state that uses the specified image.
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param manager The manager to create image request operation.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL
forState:(UIControlState)state
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(nullable YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Cancel the current backgroundImage request for a specified state.
@param state The state that uses the specified image.
*/
- (void)yy_cancelBackgroundImageRequestForState:(UIControlState)state;
@end
NS_ASSUME_NONNULL_END
//
// UIImageView+YYWebImage.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#if __has_include(<YYWebImage/YYWebImage.h>)
#import <YYWebImage/YYWebImageManager.h>
#else
#import "YYWebImageManager.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
Web image methods for UIImageView.
*/
@interface UIImageView (YYWebImage)
#pragma mark - image
/**
Current image URL.
@discussion Set a new value to this property will cancel the previous request
operation and create a new request operation to fetch image. Set nil to clear
the image and image URL.
*/
@property (nullable, nonatomic, strong) NSURL *yy_imageURL;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param options The options to use when request the image.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `image` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder he image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param manager The manager to create image request operation.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(nullable YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Cancel the current image request.
*/
- (void)yy_cancelCurrentImageRequest;
#pragma mark - highlight image
/**
Current highlighted image URL.
@discussion Set a new value to this property will cancel the previous request
operation and create a new request operation to fetch image. Set nil to clear
the highlighted image and image URL.
*/
@property (nullable, nonatomic, strong) NSURL *yy_highlightedImageURL;
/**
Set the view's `highlightedImage` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
*/
- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder;
/**
Set the view's `highlightedImage` with a specified URL.
@param imageURL The image url (remote or local file path).
@param options The options to use when request the image.
*/
- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options;
/**
Set the view's `highlightedImage` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `highlightedImage` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Set the view's `highlightedImage` with a specified URL.
@param imageURL The image url (remote or local file path).
@param placeholder The image to be set initially, until the image request finishes.
@param options The options to use when request the image.
@param manager The manager to create image request operation.
@param progress The block invoked (on main thread) during image request.
@param transform The block invoked (on background thread) to do additional image process.
@param completion The block invoked (on main thread) when image request completed.
*/
- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL
placeholder:(nullable UIImage *)placeholder
options:(YYWebImageOptions)options
manager:(nullable YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/**
Cancel the current highlighed image request.
*/
- (void)yy_cancelCurrentHighlightedImageRequest;
@end
NS_ASSUME_NONNULL_END
//
// _YYWebImageSetter.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/7/15.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#import <pthread.h>
#if __has_include(<YYWebImage/YYWebImage.h>)
#import <YYWebImage/YYWebImageManager.h>
#else
#import "YYWebImageManager.h"
#endif
NS_ASSUME_NONNULL_BEGIN
/**
Submits a block for execution on a main queue and waits until the block completes.
*/
static inline void _yy_dispatch_sync_on_main_queue(void (^block)()) {
if (pthread_main_np()) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
}
extern NSString *const _YYWebImageFadeAnimationKey;
extern const NSTimeInterval _YYWebImageFadeTime;
extern const NSTimeInterval _YYWebImageProgressiveFadeTime;
/**
Private class used by web image categories.
Typically, you should not use this class directly.
*/
@interface _YYWebImageSetter : NSObject
/// Current image url.
@property (nullable, nonatomic, readonly) NSURL *imageURL;
/// Current sentinel.
@property (nonatomic, readonly) int32_t sentinel;
/// Create new operation for web image and return a sentinel value.
- (int32_t)setOperationWithSentinel:(int32_t)sentinel
url:(nullable NSURL *)imageURL
options:(YYWebImageOptions)options
manager:(YYWebImageManager *)manager
progress:(nullable YYWebImageProgressBlock)progress
transform:(nullable YYWebImageTransformBlock)transform
completion:(nullable YYWebImageCompletionBlock)completion;
/// Cancel and return a sentinel value. The imageURL will be set to nil.
- (int32_t)cancel;
/// Cancel and return a sentinel value. The imageURL will be set to new value.
- (int32_t)cancelWithNewURL:(nullable NSURL *)imageURL;
/// A queue to set operation.
+ (dispatch_queue_t)setterQueue;
@end
NS_ASSUME_NONNULL_END
//
// _YYWebImageSetter.m
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/7/15.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "_YYWebImageSetter.h"
#import "YYWebImageOperation.h"
#import <libkern/OSAtomic.h>
NSString *const _YYWebImageFadeAnimationKey = @"YYWebImageFade";
const NSTimeInterval _YYWebImageFadeTime = 0.2;
const NSTimeInterval _YYWebImageProgressiveFadeTime = 0.4;
@implementation _YYWebImageSetter {
dispatch_semaphore_t _lock;
NSURL *_imageURL;
NSOperation *_operation;
int32_t _sentinel;
}
- (instancetype)init {
self = [super init];
_lock = dispatch_semaphore_create(1);
return self;
}
- (NSURL *)imageURL {
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
NSURL *imageURL = _imageURL;
dispatch_semaphore_signal(_lock);
return imageURL;
}
- (void)dealloc {
OSAtomicIncrement32(&_sentinel);
[_operation cancel];
}
- (int32_t)setOperationWithSentinel:(int32_t)sentinel
url:(NSURL *)imageURL
options:(YYWebImageOptions)options
manager:(YYWebImageManager *)manager
progress:(YYWebImageProgressBlock)progress
transform:(YYWebImageTransformBlock)transform
completion:(YYWebImageCompletionBlock)completion {
if (sentinel != _sentinel) {
if (completion) completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageCancelled, nil);
return _sentinel;
}
NSOperation *operation = [manager requestImageWithURL:imageURL options:options progress:progress transform:transform completion:completion];
if (!operation && completion) {
NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"YYWebImageOperation create failed." };
completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageFinished, [NSError errorWithDomain:@"com.ibireme.webimage" code:-1 userInfo:userInfo]);
}
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
if (sentinel == _sentinel) {
if (_operation) [_operation cancel];
_operation = operation;
sentinel = OSAtomicIncrement32(&_sentinel);
} else {
[operation cancel];
}
dispatch_semaphore_signal(_lock);
return sentinel;
}
- (int32_t)cancel {
return [self cancelWithNewURL:nil];
}
- (int32_t)cancelWithNewURL:(NSURL *)imageURL {
int32_t sentinel;
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
if (_operation) {
[_operation cancel];
_operation = nil;
}
_imageURL = imageURL;
sentinel = OSAtomicIncrement32(&_sentinel);
dispatch_semaphore_signal(_lock);
return sentinel;
}
+ (dispatch_queue_t)setterQueue {
static dispatch_queue_t queue;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
queue = dispatch_queue_create("com.ibireme.webimage.setter", DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
});
return queue;
}
@end
//
// YYImageCache.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/15.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
@class YYMemoryCache, YYDiskCache;
NS_ASSUME_NONNULL_BEGIN
/// Image cache type
typedef NS_OPTIONS(NSUInteger, YYImageCacheType) {
/// No value.
YYImageCacheTypeNone = 0,
/// Get/store image with memory cache.
YYImageCacheTypeMemory = 1 << 0,
/// Get/store image with disk cache.
YYImageCacheTypeDisk = 1 << 1,
/// Get/store image with both memory cache and disk cache.
YYImageCacheTypeAll = YYImageCacheTypeMemory | YYImageCacheTypeDisk,
};
/**
YYImageCache is a cache that stores UIImage and image data based on memory cache and disk cache.
@discussion The disk cache will try to protect the original image data:
* If the original image is still image, it will be saved as png/jpeg file based on alpha information.
* If the original image is animated gif, apng or webp, it will be saved as original format.
* If the original image's scale is not 1, the scale value will be saved as extended data.
Although UIImage can be serialized with NSCoding protocol, but it's not a good idea:
Apple actually use UIImagePNGRepresentation() to encode all kind of image, it may
lose the original multi-frame data. The result is packed to plist file and cannot
view with photo viewer directly. If the image has no alpha channel, using JPEG
instead of PNG can save more disk size and encoding/decoding time.
*/
@interface YYImageCache : NSObject
#pragma mark - Attribute
///=============================================================================
/// @name Attribute
///=============================================================================
/** The name of the cache. Default is nil. */
@property (nullable, copy) NSString *name;
/** The underlying memory cache. see `YYMemoryCache` for more information.*/
@property (strong, readonly) YYMemoryCache *memoryCache;
/** The underlying disk cache. see `YYDiskCache` for more information.*/
@property (strong, readonly) YYDiskCache *diskCache;
/**
Whether decode animated image when fetch image from disk cache. Default is YES.
@discussion When fetch image from disk cache, it will use 'YYImage' to decode
animated image such as WebP/APNG/GIF. Set to 'NO' to ignore animated image.
*/
@property BOOL allowAnimatedImage;
/**
Whether decode the image to memory bitmap. Default is YES.
@discussion If the value is YES, then the image will be decoded to memory bitmap
for better display performance, but may cost more memory.
*/
@property BOOL decodeForDisplay;
#pragma mark - Initializer
///=============================================================================
/// @name Initializer
///=============================================================================
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
/**
Returns global shared image cache instance.
@return The singleton YYImageCache instance.
*/
+ (instancetype)sharedCache;
/**
The designated initializer. Multiple instances with the same path will make the
cache unstable.
@param path Full path of a directory in which the cache will write data.
Once initialized you should not read and write to this directory.
@result A new cache object, or nil if an error occurs.
*/
- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
#pragma mark - Access Methods
///=============================================================================
/// @name Access Methods
///=============================================================================
/**
Sets the image with the specified key in the cache (both memory and disk).
This method returns immediately and executes the store operation in background.
@param image The image to be stored in the cache. If nil, this method has no effect.
@param key The key with which to associate the image. If nil, this method has no effect.
*/
- (void)setImage:(UIImage *)image forKey:(NSString *)key;
/**
Sets the image with the specified key in the cache.
This method returns immediately and executes the store operation in background.
@discussion If the `type` contain `YYImageCacheTypeMemory`, then the `image` will
be stored in the memory cache; `imageData` will be used instead if `image` is nil.
If the `type` contain `YYImageCacheTypeDisk`, then the `imageData` will
be stored in the disk cache; `image` will be used instead if `imageData` is nil.
@param image The image to be stored in the cache.
@param imageData The image data to be stored in the cache.
@param key The key with which to associate the image. If nil, this method has no effect.
@param type The cache type to store image.
*/
- (void)setImage:(nullable UIImage *)image
imageData:(nullable NSData *)imageData
forKey:(NSString *)key
withType:(YYImageCacheType)type;
/**
Removes the image of the specified key in the cache (both memory and disk).
This method returns immediately and executes the remove operation in background.
@param key The key identifying the image to be removed. If nil, this method has no effect.
*/
- (void)removeImageForKey:(NSString *)key;
/**
Removes the image of the specified key in the cache.
This method returns immediately and executes the remove operation in background.
@param key The key identifying the image to be removed. If nil, this method has no effect.
@param type The cache type to remove image.
*/
- (void)removeImageForKey:(NSString *)key withType:(YYImageCacheType)type;
/**
Returns a Boolean value that indicates whether a given key is in cache.
If the image is not in memory, this method may blocks the calling thread until
file read finished.
@param key A string identifying the image. If nil, just return NO.
@return Whether the image is in cache.
*/
- (BOOL)containsImageForKey:(NSString *)key;
/**
Returns a Boolean value that indicates whether a given key is in cache.
If the image is not in memory and the `type` contains `YYImageCacheTypeDisk`,
this method may blocks the calling thread until file read finished.
@param key A string identifying the image. If nil, just return NO.
@param type The cache type.
@return Whether the image is in cache.
*/
- (BOOL)containsImageForKey:(NSString *)key withType:(YYImageCacheType)type;
/**
Returns the image associated with a given key.
If the image is not in memory, this method may blocks the calling thread until
file read finished.
@param key A string identifying the image. If nil, just return nil.
@return The image associated with key, or nil if no image is associated with key.
*/
- (nullable UIImage *)getImageForKey:(NSString *)key;
/**
Returns the image associated with a given key.
If the image is not in memory and the `type` contains `YYImageCacheTypeDisk`,
this method may blocks the calling thread until file read finished.
@param key A string identifying the image. If nil, just return nil.
@return The image associated with key, or nil if no image is associated with key.
*/
- (nullable UIImage *)getImageForKey:(NSString *)key withType:(YYImageCacheType)type;
/**
Asynchronously get the image associated with a given key.
@param key A string identifying the image. If nil, just return nil.
@param type The cache type.
@param block A completion block which will be called on main thread.
*/
- (void)getImageForKey:(NSString *)key
withType:(YYImageCacheType)type
withBlock:(void(^)(UIImage * _Nullable image, YYImageCacheType type))block;
/**
Returns the image data associated with a given key.
This method may blocks the calling thread until file read finished.
@param key A string identifying the image. If nil, just return nil.
@return The image data associated with key, or nil if no image is associated with key.
*/
- (nullable NSData *)getImageDataForKey:(NSString *)key;
/**
Asynchronously get the image data associated with a given key.
@param key A string identifying the image. If nil, just return nil.
@param block A completion block which will be called on main thread.
*/
- (void)getImageDataForKey:(NSString *)key
withBlock:(void(^)(NSData * _Nullable imageData))block;
@end
NS_ASSUME_NONNULL_END
//
// YYImageCache.m
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/15.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import "YYImageCache.h"
#import "YYImage.h"
#import "UIImage+YYWebImage.h"
#if __has_include(<YYImage/YYImage.h>)
#import <YYImage/YYImage.h>
#else
#import "YYImage.h"
#endif
#if __has_include(<YYCache/YYCache.h>)
#import <YYCache/YYCache.h>
#else
#import "YYCache.h"
#endif
static inline dispatch_queue_t YYImageCacheIOQueue() {
return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
}
static inline dispatch_queue_t YYImageCacheDecodeQueue() {
return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
}
@interface YYImageCache ()
- (NSUInteger)imageCost:(UIImage *)image;
- (UIImage *)imageFromData:(NSData *)data;
@end
@implementation YYImageCache
- (NSUInteger)imageCost:(UIImage *)image {
CGImageRef cgImage = image.CGImage;
if (!cgImage) return 1;
CGFloat height = CGImageGetHeight(cgImage);
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
NSUInteger cost = bytesPerRow * height;
if (cost == 0) cost = 1;
return cost;
}
- (UIImage *)imageFromData:(NSData *)data {
NSData *scaleData = [YYDiskCache getExtendedDataFromObject:data];
CGFloat scale = 0;
if (scaleData) {
scale = ((NSNumber *)[NSKeyedUnarchiver unarchiveObjectWithData:scaleData]).doubleValue;
}
if (scale <= 0) scale = [UIScreen mainScreen].scale;
UIImage *image;
if (_allowAnimatedImage) {
image = [[YYImage alloc] initWithData:data scale:scale];
if (_decodeForDisplay) image = [image yy_imageByDecoded];
} else {
YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale];
image = [decoder frameAtIndex:0 decodeForDisplay:_decodeForDisplay].image;
}
return image;
}
#pragma mark Public
+ (instancetype)sharedCache {
static YYImageCache *cache = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES) firstObject];
cachePath = [cachePath stringByAppendingPathComponent:@"com.ibireme.yykit"];
cachePath = [cachePath stringByAppendingPathComponent:@"images"];
cache = [[self alloc] initWithPath:cachePath];
});
return cache;
}
- (instancetype)init {
@throw [NSException exceptionWithName:@"YYImageCache init error" reason:@"YYImageCache must be initialized with a path. Use 'initWithPath:' instead." userInfo:nil];
return [self initWithPath:@""];
}
- (instancetype)initWithPath:(NSString *)path {
YYMemoryCache *memoryCache = [YYMemoryCache new];
memoryCache.shouldRemoveAllObjectsOnMemoryWarning = YES;
memoryCache.shouldRemoveAllObjectsWhenEnteringBackground = YES;
memoryCache.countLimit = NSUIntegerMax;
memoryCache.costLimit = NSUIntegerMax;
memoryCache.ageLimit = 12 * 60 * 60;
YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path];
diskCache.customArchiveBlock = ^(id object) { return (NSData *)object; };
diskCache.customUnarchiveBlock = ^(NSData *data) { return (id)data; };
if (!memoryCache || !diskCache) return nil;
self = [super init];
_memoryCache = memoryCache;
_diskCache = diskCache;
_allowAnimatedImage = YES;
_decodeForDisplay = YES;
return self;
}
- (void)setImage:(UIImage *)image forKey:(NSString *)key {
[self setImage:image imageData:nil forKey:key withType:YYImageCacheTypeAll];
}
- (void)setImage:(UIImage *)image imageData:(NSData *)imageData forKey:(NSString *)key withType:(YYImageCacheType)type {
if (!key || (image == nil && imageData.length == 0)) return;
__weak typeof(self) _self = self;
if (type & YYImageCacheTypeMemory) { // add to memory cache
if (image) {
if (image.yy_isDecodedForDisplay) {
[_memoryCache setObject:image forKey:key withCost:[_self imageCost:image]];
} else {
dispatch_async(YYImageCacheDecodeQueue(), ^{
__strong typeof(_self) self = _self;
if (!self) return;
[self.memoryCache setObject:[image yy_imageByDecoded] forKey:key withCost:[self imageCost:image]];
});
}
} else if (imageData) {
dispatch_async(YYImageCacheDecodeQueue(), ^{
__strong typeof(_self) self = _self;
if (!self) return;
UIImage *newImage = [self imageFromData:imageData];
[self.memoryCache setObject:newImage forKey:key withCost:[self imageCost:newImage]];
});
}
}
if (type & YYImageCacheTypeDisk) { // add to disk cache
if (imageData) {
if (image) {
[YYDiskCache setExtendedData:[NSKeyedArchiver archivedDataWithRootObject:@(image.scale)] toObject:imageData];
}
[_diskCache setObject:imageData forKey:key];
} else if (image) {
dispatch_async(YYImageCacheIOQueue(), ^{
__strong typeof(_self) self = _self;
if (!self) return;
NSData *data = [image yy_imageDataRepresentation];
[YYDiskCache setExtendedData:[NSKeyedArchiver archivedDataWithRootObject:@(image.scale)] toObject:data];
[self.diskCache setObject:data forKey:key];
});
}
}
}
- (void)removeImageForKey:(NSString *)key {
[self removeImageForKey:key withType:YYImageCacheTypeAll];
}
- (void)removeImageForKey:(NSString *)key withType:(YYImageCacheType)type {
if (type & YYImageCacheTypeMemory) [_memoryCache removeObjectForKey:key];
if (type & YYImageCacheTypeDisk) [_diskCache removeObjectForKey:key];
}
- (BOOL)containsImageForKey:(NSString *)key {
return [self containsImageForKey:key withType:YYImageCacheTypeAll];
}
- (BOOL)containsImageForKey:(NSString *)key withType:(YYImageCacheType)type {
if (type & YYImageCacheTypeMemory) {
if ([_memoryCache containsObjectForKey:key]) return YES;
}
if (type & YYImageCacheTypeDisk) {
if ([_diskCache containsObjectForKey:key]) return YES;
}
return NO;
}
- (UIImage *)getImageForKey:(NSString *)key {
return [self getImageForKey:key withType:YYImageCacheTypeAll];
}
- (UIImage *)getImageForKey:(NSString *)key withType:(YYImageCacheType)type {
if (!key) return nil;
if (type & YYImageCacheTypeMemory) {
UIImage *image = [_memoryCache objectForKey:key];
if (image) return image;
}
if (type & YYImageCacheTypeDisk) {
NSData *data = (id)[_diskCache objectForKey:key];
UIImage *image = [self imageFromData:data];
if (image && (type & YYImageCacheTypeMemory)) {
[_memoryCache setObject:image forKey:key withCost:[self imageCost:image]];
}
return image;
}
return nil;
}
- (void)getImageForKey:(NSString *)key withType:(YYImageCacheType)type withBlock:(void (^)(UIImage *image, YYImageCacheType type))block {
if (!block) return;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = nil;
if (type & YYImageCacheTypeMemory) {
image = [_memoryCache objectForKey:key];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
block(image, YYImageCacheTypeMemory);
});
return;
}
}
if (type & YYImageCacheTypeDisk) {
NSData *data = (id)[_diskCache objectForKey:key];
image = [self imageFromData:data];
if (image) {
[_memoryCache setObject:image forKey:key];
dispatch_async(dispatch_get_main_queue(), ^{
block(image, YYImageCacheTypeDisk);
});
return;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
block(nil, YYImageCacheTypeNone);
});
});
}
- (NSData *)getImageDataForKey:(NSString *)key {
return (id)[_diskCache objectForKey:key];
}
- (void)getImageDataForKey:(NSString *)key withBlock:(void (^)(NSData *imageData))block {
if (!block) return;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = (id)[_diskCache objectForKey:key];
dispatch_async(dispatch_get_main_queue(), ^{
block(data);
});
});
}
@end
//
// YYWebImage.h
// YYWebImage <https://github.com/ibireme/YYWebImage>
//
// Created by ibireme on 15/2/23.
// Copyright (c) 2015 ibireme.
//
// This source code is licensed under the MIT-style license found in the
// LICENSE file in the root directory of this source tree.
//
#import <UIKit/UIKit.h>
#if __has_include(<YYWebImage/YYWebImage.h>)
FOUNDATION_EXPORT double YYWebImageVersionNumber;
FOUNDATION_EXPORT const unsigned char YYWebImageVersionString[];
#import <YYWebImage/YYImageCache.h>
#import <YYWebImage/YYWebImageOperation.h>
#import <YYWebImage/YYWebImageManager.h>
#import <YYWebImage/UIImage+YYWebImage.h>
#import <YYWebImage/UIImageView+YYWebImage.h>
#import <YYWebImage/UIButton+YYWebImage.h>
#import <YYWebImage/CALayer+YYWebImage.h>
#import <YYWebImage/MKAnnotationView+YYWebImage.h>
#else
#import "YYImageCache.h"
#import "YYWebImageOperation.h"
#import "YYWebImageManager.h"
#import "UIImage+YYWebImage.h"
#import "UIImageView+YYWebImage.h"
#import "UIButton+YYWebImage.h"
#import "CALayer+YYWebImage.h"
#import "MKAnnotationView+YYWebImage.h"
#endif
#if __has_include(<YYImage/YYImage.h>)
#import <YYImage/YYImage.h>
#elif __has_include(<YYWebImage/YYImage.h>)
#import <YYWebImage/YYImage.h>
#import <YYWebImage/YYFrameImage.h>
#import <YYWebImage/YYSpriteSheetImage.h>
#import <YYWebImage/YYImageCoder.h>
#import <YYWebImage/YYAnimatedImageView.h>
#else
#import "YYImage.h"
#import "YYFrameImage.h"
#import "YYSpriteSheetImage.h"
#import "YYImageCoder.h"
#import "YYAnimatedImageView.h"
#endif
#if __has_include(<YYCache/YYCache.h>)
#import <YYCache/YYCache.h>
#elif __has_include(<YYWebImage/YYCache.h>)
#import <YYWebImage/YYCache.h>
#import <YYWebImage/YYMemoryCache.h>
#import <YYWebImage/YYDiskCache.h>
#import <YYWebImage/YYKVStorage.h>
#else
#import "YYCache.h"
#import "YYMemoryCache.h"
#import "YYDiskCache.h"
#import "YYKVStorage.h"
#endif
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!