diff --git a/Demo/Podfile b/Demo/Podfile index 1f1bb79b..56b1a237 100644 --- a/Demo/Podfile +++ b/Demo/Podfile @@ -5,4 +5,5 @@ inhibit_all_warnings! project 'XMNetworkingDemo' target 'XMNetworkingDemo' do pod 'AFNetworking', '~> 3.0' -end \ No newline at end of file + pod 'YYCache' +end diff --git a/Demo/Podfile.lock b/Demo/Podfile.lock index 492f5a8f..edbb88e5 100644 --- a/Demo/Podfile.lock +++ b/Demo/Podfile.lock @@ -1,30 +1,34 @@ PODS: - - AFNetworking (3.2.0): - - AFNetworking/NSURLSession (= 3.2.0) - - AFNetworking/Reachability (= 3.2.0) - - AFNetworking/Security (= 3.2.0) - - AFNetworking/Serialization (= 3.2.0) - - AFNetworking/UIKit (= 3.2.0) - - AFNetworking/NSURLSession (3.2.0): + - AFNetworking (3.2.1): + - AFNetworking/NSURLSession (= 3.2.1) + - AFNetworking/Reachability (= 3.2.1) + - AFNetworking/Security (= 3.2.1) + - AFNetworking/Serialization (= 3.2.1) + - AFNetworking/UIKit (= 3.2.1) + - AFNetworking/NSURLSession (3.2.1): - AFNetworking/Reachability - AFNetworking/Security - AFNetworking/Serialization - - AFNetworking/Reachability (3.2.0) - - AFNetworking/Security (3.2.0) - - AFNetworking/Serialization (3.2.0) - - AFNetworking/UIKit (3.2.0): + - AFNetworking/Reachability (3.2.1) + - AFNetworking/Security (3.2.1) + - AFNetworking/Serialization (3.2.1) + - AFNetworking/UIKit (3.2.1): - AFNetworking/NSURLSession + - YYCache (1.0.4) DEPENDENCIES: - AFNetworking (~> 3.0) + - YYCache SPEC REPOS: - https://github.com/CocoaPods/Specs.git: + https://github.com/cocoapods/specs.git: - AFNetworking + - YYCache SPEC CHECKSUMS: - AFNetworking: 8ac6017b94ea105479f7776e5288e48ae9c59bb4 + AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057 + YYCache: 8105b6638f5e849296c71f331ff83891a4942952 -PODFILE CHECKSUM: 34f6387ee40deb3469deca752658f6f8e19eebbf +PODFILE CHECKSUM: fbd06ec2977b699c1a1c4f502b299f924960379d -COCOAPODS: 1.5.0 +COCOAPODS: 1.5.3 diff --git a/Demo/Pods/AFNetworking/AFNetworking/AFCompatibilityMacros.h b/Demo/Pods/AFNetworking/AFNetworking/AFCompatibilityMacros.h new file mode 100644 index 00000000..a83d1344 --- /dev/null +++ b/Demo/Pods/AFNetworking/AFNetworking/AFCompatibilityMacros.h @@ -0,0 +1,37 @@ +// AFCompatibilityMacros.h +// Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ ) +// +// 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. + +#ifndef AFCompatibilityMacros_h +#define AFCompatibilityMacros_h + +#ifdef API_UNAVAILABLE + #define AF_API_UNAVAILABLE(x) API_UNAVAILABLE(x) +#else + #define AF_API_UNAVAILABLE(x) +#endif // API_UNAVAILABLE + +#if __has_warning("-Wunguarded-availability-new") + #define AF_CAN_USE_AT_AVAILABLE 1 +#else + #define AF_CAN_USE_AT_AVAILABLE 0 +#endif + +#endif /* AFCompatibilityMacros_h */ diff --git a/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h b/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h index 72296d49..21982a0e 100644 --- a/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h +++ b/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.h @@ -108,11 +108,14 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; /** - * Initializes an instance of a network reachability manager - * - * @return nil as this method is unavailable + * Unavailable initializer */ -- (nullable instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Unavailable initializer + */ +- (instancetype)init NS_UNAVAILABLE; ///-------------------------------------------------- /// @name Starting & Stopping Reachability Monitoring diff --git a/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m b/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m index d4583648..ce746c38 100644 --- a/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m +++ b/Demo/Pods/AFNetworking/AFNetworking/AFNetworkReachabilityManager.m @@ -170,8 +170,11 @@ - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { return self; } -- (instancetype)init NS_UNAVAILABLE +- (instancetype)init { + @throw [NSException exceptionWithName:NSGenericException + reason:@"`-init` unavailable. Use `-initWithReachability:` instead" + userInfo:nil]; return nil; } diff --git a/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h b/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h index d2b28ce6..e7ae0d8e 100644 --- a/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h +++ b/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.h @@ -25,6 +25,7 @@ #import "AFURLResponseSerialization.h" #import "AFURLRequestSerialization.h" #import "AFSecurityPolicy.h" +#import "AFCompatibilityMacros.h" #if !TARGET_OS_WATCH #import "AFNetworkReachabilityManager.h" #endif @@ -414,7 +415,7 @@ NS_ASSUME_NONNULL_BEGIN @param block A block object to be executed once all messages enqueued for a session have been delivered. The block has no return value and takes a single argument: the session. */ -- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block; +- (void)setDidFinishEventsForBackgroundURLSessionBlock:(nullable void (^)(NSURLSession *session))block AF_API_UNAVAILABLE(macos); ///----------------------------------------------- /// @name Setting Download Task Delegate Callbacks diff --git a/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m b/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m index 9586c75c..aeb1af39 100644 --- a/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m +++ b/Demo/Pods/AFNetworking/AFNetworking/AFURLSessionManager.m @@ -148,15 +148,17 @@ - (instancetype)initWithTask:(NSURLSessionTask *)task { progress.pausingHandler = ^{ [weakTask suspend]; }; -#if __has_warning("-Wunguarded-availability-new") - if (@available(iOS 9, macOS 10.11, *)) { +#if AF_CAN_USE_AT_AVAILABLE + if (@available(iOS 9, macOS 10.11, *)) #else - if ([progress respondsToSelector:@selector(setResumingHandler:)]) { + if ([progress respondsToSelector:@selector(setResumingHandler:)]) #endif + { progress.resumingHandler = ^{ [weakTask resume]; }; } + [progress addObserver:self forKeyPath:NSStringFromSelector(@selector(fractionCompleted)) options:NSKeyValueObservingOptionNew @@ -452,7 +454,7 @@ @interface AFURLSessionManager () @property (readwrite, nonatomic, strong) NSLock *lock; @property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid; @property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge; -@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession; +@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession AF_API_UNAVAILABLE(macos); @property (readwrite, nonatomic, copy) AFURLSessionTaskWillPerformHTTPRedirectionBlock taskWillPerformHTTPRedirection; @property (readwrite, nonatomic, copy) AFURLSessionTaskDidReceiveAuthenticationChallengeBlock taskDidReceiveAuthenticationChallenge; @property (readwrite, nonatomic, copy) AFURLSessionTaskNeedNewBodyStreamBlock taskNeedNewBodyStream; @@ -839,9 +841,11 @@ - (void)setSessionDidReceiveAuthenticationChallengeBlock:(NSURLSessionAuthChalle self.sessionDidReceiveAuthenticationChallenge = block; } +#if !TARGET_OS_OSX - (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block { self.didFinishEventsForBackgroundURLSession = block; } +#endif #pragma mark - @@ -910,9 +914,12 @@ - (BOOL)respondsToSelector:(SEL)selector { return self.dataTaskDidReceiveResponse != nil; } else if (selector == @selector(URLSession:dataTask:willCacheResponse:completionHandler:)) { return self.dataTaskWillCacheResponse != nil; - } else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) { + } +#if !TARGET_OS_OSX + else if (selector == @selector(URLSessionDidFinishEventsForBackgroundURLSession:)) { return self.didFinishEventsForBackgroundURLSession != nil; } +#endif return [[self class] instancesRespondToSelector:selector]; } @@ -1130,6 +1137,7 @@ - (void)URLSession:(NSURLSession *)session } } +#if !TARGET_OS_OSX - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { if (self.didFinishEventsForBackgroundURLSession) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -1137,6 +1145,7 @@ - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session }); } } +#endif #pragma mark - NSURLSessionDownloadDelegate diff --git a/Demo/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m b/Demo/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m index 1f0a7786..41c18a61 100644 --- a/Demo/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m +++ b/Demo/Pods/AFNetworking/UIKit+AFNetworking/UIImageView+AFNetworking.m @@ -75,17 +75,20 @@ - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure { - + if ([urlRequest URL] == nil) { - [self cancelImageDownloadTask]; self.image = placeholderImage; + if (failure) { + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil]; + failure(urlRequest, nil, error); + } return; } - + if ([self isActiveTaskURLEqualToURLRequest:urlRequest]){ return; } - + [self cancelImageDownloadTask]; AFImageDownloader *downloader = [[self class] sharedImageDownloader]; diff --git a/Demo/Pods/Headers/Private/AFNetworking/AFCompatibilityMacros.h b/Demo/Pods/Headers/Private/AFNetworking/AFCompatibilityMacros.h new file mode 120000 index 00000000..487b3fee --- /dev/null +++ b/Demo/Pods/Headers/Private/AFNetworking/AFCompatibilityMacros.h @@ -0,0 +1 @@ +../../../AFNetworking/AFNetworking/AFCompatibilityMacros.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Private/YYCache/YYCache.h b/Demo/Pods/Headers/Private/YYCache/YYCache.h new file mode 120000 index 00000000..2ba9cf81 --- /dev/null +++ b/Demo/Pods/Headers/Private/YYCache/YYCache.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYCache.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Private/YYCache/YYDiskCache.h b/Demo/Pods/Headers/Private/YYCache/YYDiskCache.h new file mode 120000 index 00000000..9627fddb --- /dev/null +++ b/Demo/Pods/Headers/Private/YYCache/YYDiskCache.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYDiskCache.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Private/YYCache/YYKVStorage.h b/Demo/Pods/Headers/Private/YYCache/YYKVStorage.h new file mode 120000 index 00000000..ac9f3181 --- /dev/null +++ b/Demo/Pods/Headers/Private/YYCache/YYKVStorage.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYKVStorage.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Private/YYCache/YYMemoryCache.h b/Demo/Pods/Headers/Private/YYCache/YYMemoryCache.h new file mode 120000 index 00000000..e33b84c7 --- /dev/null +++ b/Demo/Pods/Headers/Private/YYCache/YYMemoryCache.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYMemoryCache.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Public/AFNetworking/AFCompatibilityMacros.h b/Demo/Pods/Headers/Public/AFNetworking/AFCompatibilityMacros.h new file mode 120000 index 00000000..487b3fee --- /dev/null +++ b/Demo/Pods/Headers/Public/AFNetworking/AFCompatibilityMacros.h @@ -0,0 +1 @@ +../../../AFNetworking/AFNetworking/AFCompatibilityMacros.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Public/YYCache/YYCache.h b/Demo/Pods/Headers/Public/YYCache/YYCache.h new file mode 120000 index 00000000..2ba9cf81 --- /dev/null +++ b/Demo/Pods/Headers/Public/YYCache/YYCache.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYCache.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Public/YYCache/YYDiskCache.h b/Demo/Pods/Headers/Public/YYCache/YYDiskCache.h new file mode 120000 index 00000000..9627fddb --- /dev/null +++ b/Demo/Pods/Headers/Public/YYCache/YYDiskCache.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYDiskCache.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Public/YYCache/YYKVStorage.h b/Demo/Pods/Headers/Public/YYCache/YYKVStorage.h new file mode 120000 index 00000000..ac9f3181 --- /dev/null +++ b/Demo/Pods/Headers/Public/YYCache/YYKVStorage.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYKVStorage.h \ No newline at end of file diff --git a/Demo/Pods/Headers/Public/YYCache/YYMemoryCache.h b/Demo/Pods/Headers/Public/YYCache/YYMemoryCache.h new file mode 120000 index 00000000..e33b84c7 --- /dev/null +++ b/Demo/Pods/Headers/Public/YYCache/YYMemoryCache.h @@ -0,0 +1 @@ +../../../YYCache/YYCache/YYMemoryCache.h \ No newline at end of file diff --git a/Demo/Pods/Manifest.lock b/Demo/Pods/Manifest.lock index 492f5a8f..edbb88e5 100644 --- a/Demo/Pods/Manifest.lock +++ b/Demo/Pods/Manifest.lock @@ -1,30 +1,34 @@ PODS: - - AFNetworking (3.2.0): - - AFNetworking/NSURLSession (= 3.2.0) - - AFNetworking/Reachability (= 3.2.0) - - AFNetworking/Security (= 3.2.0) - - AFNetworking/Serialization (= 3.2.0) - - AFNetworking/UIKit (= 3.2.0) - - AFNetworking/NSURLSession (3.2.0): + - AFNetworking (3.2.1): + - AFNetworking/NSURLSession (= 3.2.1) + - AFNetworking/Reachability (= 3.2.1) + - AFNetworking/Security (= 3.2.1) + - AFNetworking/Serialization (= 3.2.1) + - AFNetworking/UIKit (= 3.2.1) + - AFNetworking/NSURLSession (3.2.1): - AFNetworking/Reachability - AFNetworking/Security - AFNetworking/Serialization - - AFNetworking/Reachability (3.2.0) - - AFNetworking/Security (3.2.0) - - AFNetworking/Serialization (3.2.0) - - AFNetworking/UIKit (3.2.0): + - AFNetworking/Reachability (3.2.1) + - AFNetworking/Security (3.2.1) + - AFNetworking/Serialization (3.2.1) + - AFNetworking/UIKit (3.2.1): - AFNetworking/NSURLSession + - YYCache (1.0.4) DEPENDENCIES: - AFNetworking (~> 3.0) + - YYCache SPEC REPOS: - https://github.com/CocoaPods/Specs.git: + https://github.com/cocoapods/specs.git: - AFNetworking + - YYCache SPEC CHECKSUMS: - AFNetworking: 8ac6017b94ea105479f7776e5288e48ae9c59bb4 + AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057 + YYCache: 8105b6638f5e849296c71f331ff83891a4942952 -PODFILE CHECKSUM: 34f6387ee40deb3469deca752658f6f8e19eebbf +PODFILE CHECKSUM: fbd06ec2977b699c1a1c4f502b299f924960379d -COCOAPODS: 1.5.0 +COCOAPODS: 1.5.3 diff --git a/Demo/Pods/Pods.xcodeproj/project.pbxproj b/Demo/Pods/Pods.xcodeproj/project.pbxproj index 66b1217a..cff27892 100644 --- a/Demo/Pods/Pods.xcodeproj/project.pbxproj +++ b/Demo/Pods/Pods.xcodeproj/project.pbxproj @@ -7,182 +7,198 @@ objects = { /* Begin PBXBuildFile section */ - 0214246CCB1FF7182F7222B9CCDF8FCB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F921D275AC6AA48C031BF91FD4592584 /* Foundation.framework */; }; - 064EC4AA8FCCD08F2037037B1E672DBF /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 809E0EE6429DA2700D30D5F8F46F4100 /* AFURLSessionManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0A1CE7CE58B28609B573D4058ABDD616 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B8C2F3F38AC8B05D07C9BAACD044EAD /* AFSecurityPolicy.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 0E642705E9D54540F88AF54A2EFA918F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F921D275AC6AA48C031BF91FD4592584 /* Foundation.framework */; }; - 12FCB056A2B7051B0D91B16CAFE85C1D /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = CC618B900858F4F77C2746363E77B86C /* UIRefreshControl+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 1702DB74CC573578862AA584FC9D1632 /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AFF2CC19E35B6A289DF5C325A6C2B4E7 /* AFNetworkActivityIndicatorManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 17889562A613EFB9E8C0CD14947CCC8F /* AFAutoPurgingImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 18A6CC7151721E485930D715056633ED /* AFAutoPurgingImageCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 17E74D623462991F19748A7F99CF8ED6 /* UIWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 51204DFB5BF601D556D71C3736263351 /* UIWebView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 19CFCF718B674B91847980FA20429558 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4852ABEFD7FFFAE072C5835CCDB22279 /* AFNetworkReachabilityManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 211646AEE68A3577495B0DF917A0DCDC /* AFImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 8006E5A6F0951AA637FFA7F53DBA00D9 /* AFImageDownloader.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2612D2B9BEA56B8CB2B361AA0BAB599F /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 516F3F2A9B24B2E2092E84E8EAF0A9F7 /* UIButton+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 29D221887670387A248AD92AA94253C2 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 525066ED64B26EC45F9B2AD4D3B0D1B2 /* AFURLSessionManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 2BCD3F861A5F4CF448072C4692AD130D /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E9837C7FFCFC4203B1BAADAADD8E206 /* UIImageView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 2E093B774E17FC557A5815F454077404 /* Pods-XMNetworkingDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B84B129073C735F3F551986CD4C07BE /* Pods-XMNetworkingDemo-dummy.m */; }; - 5D437F5C4A12A4552070DCFCC423583B /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 18B9DCDB5BE79C17D786D046D23A6C8F /* AFURLRequestSerialization.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 63299DE5DEA29075FADA35711169188E /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 14F2B0D3DD13B76429F713F1F1A1CC6F /* AFNetworking-dummy.m */; }; - 63FF4EC1D3DDA4B5ED2F68BFC306B2BF /* UIWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 036FDD48539129C05AAE4C9ACA312100 /* UIWebView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7482DD9AE507E2E744A01F061D7C9266 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 1207584E6BDCF4C846A1DDFE0BCFEECF /* UIProgressView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 75D4D1F473F6DA208001A46179BAEB7A /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 0401DF9E61B17C3AE9FE93347CCD9E64 /* AFSecurityPolicy.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 7B12269BEFA5305C78EC3D22AB2B1CEC /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D925E789318555435D0DBEF9BEC8015 /* UIActivityIndicatorView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - 8962061859D3579C36C4703E96D8F3FD /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = C23C3983ADC1EBC0A6AD3D68F3DBC4BA /* UIImageView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 903158692A045396106CA22C0DD13BA6 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC8A7C0B6179467051ED95E59DB2AF9F /* SystemConfiguration.framework */; }; - 945F691AD18DC2361A75C6621E42461C /* AFImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B17FF80B117EDDFBD41C5C3B5C1D217 /* AFImageDownloader.h */; settings = {ATTRIBUTES = (Project, ); }; }; - A906A376A93C1C83BB89E8F63A663F43 /* AFAutoPurgingImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 1246CB48952FF37C1DB54894C46F6390 /* AFAutoPurgingImageCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - AFC6DC1967B85742B8ECA969CED51610 /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = E451FBBEE5D302A74D966AC502CE5B19 /* UIActivityIndicatorView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B3B907CDAF7FDC60BFE105DDB4B51B6A /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = BFD303D6F6C659A55A8684008D1476CB /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - B43CDF265CF01D7C6072082897C51DEE /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 20CB1302DD85B80CBADE42E436CF5930 /* UIKit+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - C4D12D56B5E4323CDE6A77AEF30D4D9F /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E990D35FEF51D7420F303E35DCBE1F6 /* AFURLResponseSerialization.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - C60E5845068B90D7760411CE582C2934 /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = E71FC5436C29FCEB72394E7117726B8F /* AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - CBCCEAD402645565401CA93924736979 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A64716173FC0305057230E14CDCC7A77 /* CoreGraphics.framework */; }; - D486C538AE3151018303619712539B4C /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = D0F90194E52430599383549278FEA918 /* UIProgressView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - D542E74CF3A429E7433464C12405F07B /* UIImage+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = C0DC8653B61F64B5FC03BFC2B0A6E528 /* UIImage+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - DE825B8F32AB823F4BE5492CAC6FCB4B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12A9374C39A6EFA90AD3F2E64799ECC5 /* Security.framework */; }; - E66EDE92DE4B13E4853191475509CDFB /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 42C03FCF30AB48A3B8DC805A289477E2 /* AFHTTPSessionManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; - E81A3DDBBA7965126D98EEA4C35E7363 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 42EAD270211F301E809EA7C39D05A3DC /* AFHTTPSessionManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - EDEDABB0A7CE2131C2CF03E094C1840D /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 8946DE00AC08571F0D4A4F985A8FA609 /* AFURLResponseSerialization.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F4AF1BA06F07E566D12446F8AB86C929 /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 78C774AEA3474BF09AD285C28E701D5F /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; - F8B71BB9667E21385D7AAEFEC796BAE4 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FE9DC137B1B02C802E7ABBECC9401A7B /* AFNetworkActivityIndicatorManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - F8DCA6C3C05A59B2C95A1B5F1CBD8C99 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9FDBCCB266ACFED93E55656FD8A014C /* MobileCoreServices.framework */; }; - FB9AA5207284E33FFC55FEB308BFA71F /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = D2792B01BCFFB8C68B0CE56421B99A2F /* AFURLRequestSerialization.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; - FC0BDC904394B55C2E9C3A8C308E8EB6 /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 357FC25AA9F2E82213C986CE50969E1A /* AFNetworkReachabilityManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 159B47380CE1D5B8F6210E9D635DA7A0 /* Pods-XMNetworkingDemo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B84B129073C735F3F551986CD4C07BE /* Pods-XMNetworkingDemo-dummy.m */; }; + 18A0969FF6EEC2C58A7D4D4AAB7C6060 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B0CFEBD5CF113BAEF885005E1B20817 /* MobileCoreServices.framework */; }; + 2633BE2E887BB96BEB21584B65131AF8 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DDF3DFD447607191A69D235243063BA7 /* AFURLSessionManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 26873CE294135E7F21A809C79C117DEB /* UIImageView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 24247D459B43F22C1044FA8916DC38B4 /* UIImageView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 2753EF5BCBEC5A53CC7115842D69A226 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 26EF6AA8212E60AFDE9EF12EAB1C3502 /* AFSecurityPolicy.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 2C67FD363E5EFED189C3F8277F6B1F1F /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 2ED4D6CF9C87F1B0EBF2570B29F72D47 /* AFURLResponseSerialization.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 302888D10A449158C46614ABA5B42B22 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 335C07088BD4F6ADB9489C618B1D5BF8 /* AFHTTPSessionManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3334746D072810854256D338A2AB0C0D /* UIActivityIndicatorView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BA9491ED4243D33B0A9307456D16183 /* UIActivityIndicatorView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 3394570B7C6385D92DDEDEC22D2BB9DE /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5FCC3828D99C0750B59CE76BE103E097 /* YYCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 381B7AE4D90DB87F384B22E7C1540901 /* UIRefreshControl+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 1226405238B40DA0DDF7058EEB271945 /* UIRefreshControl+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 394685034942F5FA49C1E8A0CCFD93F9 /* UIKit+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = FF1B46D89D554BA82A58F69AE273D1F5 /* UIKit+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 3BE2B8DF14E40C80FD77000DFF97E1F2 /* AFURLResponseSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = B8D39186E250DF2331FDD3EDAEBE05D2 /* AFURLResponseSerialization.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 444C42DCE893C47FC935496EB2CD4A17 /* UIButton+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D695D934E10A7A6A543AFE0DC22731B /* UIButton+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4454F5B3AFC67E6A741186DD20859313 /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 33EB56582E901F3F811B6C96E1D5EBCE /* YYMemoryCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4491C6FB6EDAAF0D5EE72D84FC7FD902 /* YYKVStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = 44F5891E4BCD119B26B6C6FE416E7CE2 /* YYKVStorage.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 452FA80139D393F7212F57FC157E5A8E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFCFF8BCF5FDF94C2E5566CFF8820780 /* CoreGraphics.framework */; }; + 456F377DD03B42CFD65943C1347E0940 /* AFImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A2478B976691B622F46FE62E02AD2FE /* AFImageDownloader.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 4AB16F37F3DB310D29874942A952568B /* UIImage+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D37A8871B818EB31B57B46446EF8F5F /* UIImage+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 4D203CC08A98E696BDCD6A3578C5DA1B /* UIWebView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B803F81AAA6B0FE5FD48B1C8156DC70 /* UIWebView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 5D925CF6BBFA9010A254C57AAA9FB9B1 /* YYMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A3B9F0F74EF7E3F6AB63A81B46849E91 /* YYMemoryCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 65F56DD218227209F7AFCF2A15EDCE2D /* AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB86D5093EB03A862C5463BEFDA8AB5 /* AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 67CC31341F522E0D3F13A0411613DE92 /* AFNetworking-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EA5B72AC7C85E91BF2F8C7382019721F /* AFNetworking-dummy.m */; }; + 68E1B2F45F100C41D956371BABA541B7 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 198AC3304C840F87ED8DC9BCF0DE9F36 /* AFNetworkReachabilityManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6913AF9BFAD48198FAC591BE7759B842 /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 315AD1E90448E69479D38FC22293A41F /* UIImageView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 6B5E29AF5CC52D74BF3101BC7E2C59A1 /* AFCompatibilityMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = ACD6D73DF3160687513B28C70CEF7111 /* AFCompatibilityMacros.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 75D068B7AEF4C2B0CBA6E640C37CD041 /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B5B6C371805F7F75BD3C39A2787DE06 /* YYKVStorage.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 797A35DC27FF6FC03A1FCE70C458E47F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30AB58768F8C9A5F911BA6893F8B33A3 /* UIKit.framework */; }; + 7B6C0C29E2AC0F93F9C525BC89123049 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 190454DAF922532883BDAF1C9F40CC11 /* SystemConfiguration.framework */; }; + 7B93B208696C809BDB323361C138A900 /* YYCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 984423C823C40DF330BF6C4F0AD0492C /* YYCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 82640F9EE0076F032567A8C1E3EDDA82 /* AFAutoPurgingImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = B749E050B7F95CFDA2800E7065AAA454 /* AFAutoPurgingImageCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 8BFDD24EA734D85A262AAE9A3AA33222 /* UIProgressView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 04179ADEB3E48D00177401CE2AE6D65A /* UIProgressView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9272085131E5B9072B7C0F4B21008A6D /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FE42CB4E95256AAD8745E58C31DBE55 /* AFNetworkReachabilityManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 97ACF1603BEF20B66F0058CCF0AE05B2 /* AFImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B40D1BF112013A0EC9DA3DF93F7E496 /* AFImageDownloader.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 9B5B00119CD6F9D1A88FA33EA3931116 /* UIRefreshControl+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 8A0B4CCC176F6AD325A29D6622B5738C /* UIRefreshControl+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + 9C979E541C3F371E7CF1A8E1B64D45AF /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E4EDF48A24DDB92B0D2F8F47CBF3992 /* YYDiskCache.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + A8EEBDE76CBA2183583E6E49B176A3C4 /* YYCache-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5A308217A0D49B581E696BB92EDE39B5 /* YYCache-dummy.m */; }; + A9F1387B1C0A79677DDC636B8F9E6517 /* UIProgressView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = D988EE36AC007E295DF56FBDE2B81809 /* UIProgressView+AFNetworking.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + AB5E0668ECE58C8965EACB5078BA644A /* AFHTTPSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6681F556D8866BC59DA392801716A7E3 /* AFHTTPSessionManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C1D7647AD60CE3CCD9D86B030A36E442 /* UIActivityIndicatorView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = 16CC9279D47341846F1F0C3E768E37B3 /* UIActivityIndicatorView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + C71CCE388FB703FD7EB6B82D56B959AF /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BE228D49C6209E9CFDAA7271061A3A8 /* AFURLRequestSerialization.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + C973E131940932D82E6B18C79BDE6AFF /* AFURLRequestSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = DF61E6338A039FBCE54BFF53F13E877E /* AFURLRequestSerialization.h */; settings = {ATTRIBUTES = (Project, ); }; }; + CAFC9622F9174BACE6787BC24E3E4444 /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 05F2E6593553C9A088B389782E4C21F6 /* AFSecurityPolicy.h */; settings = {ATTRIBUTES = (Project, ); }; }; + D2BF2A30F845978BD2257306C0A0F4F4 /* AFNetworkActivityIndicatorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 997BFFA88BC31074D829CCF307743591 /* AFNetworkActivityIndicatorManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DB11D96468F2FB045746DB2DC9EC878A /* AFAutoPurgingImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D5C7DA2AE09D4E03472AEE872A4D0195 /* AFAutoPurgingImageCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + DE737B5DADB0D0FF1E6029228BF393FA /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 28E9A9AD2AC0A8BC2272B796F69C99EA /* AFNetworkActivityIndicatorManager.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; }; + E28D315C00C8F9CD7D3A4887E94D6DAA /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = F06418D52F85291D487E2C732B183375 /* AFURLSessionManager.h */; settings = {ATTRIBUTES = (Project, ); }; }; + E3F841BB93F4B4AA90D24C99D397CFB8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49A3B5A7EC09B485BB64FFC5BAE15BA2 /* QuartzCore.framework */; }; + E5805C68A8E165853A7D91C10B9C1A89 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A43070D0130B6016EEC95897E9697256 /* CoreFoundation.framework */; }; + EC04F2F828BAADBAB9FA13518F1F2EE7 /* UIWebView+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = A0095B1DE3FF957383DE012EE95B5FD4 /* UIWebView+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + EC6F67D55D8FCDF3F76FF6D16A491BF7 /* UIButton+AFNetworking.h in Headers */ = {isa = PBXBuildFile; fileRef = C893579BAB23C4558D4A5E761AB00E1F /* UIButton+AFNetworking.h */; settings = {ATTRIBUTES = (Project, ); }; }; + F48BF55BC20DB817E7F3BB82F939E6D6 /* YYDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = AD54A9E36C85A3B23F8994B420002CAD /* YYDiskCache.h */; settings = {ATTRIBUTES = (Project, ); }; }; + FEDC1552CAE6D0410E6A27D827B0EF1B /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0CF3695F745920B984D721E171552FB /* Security.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - B8362C42B85B9FF74CFC6AF08A7143EF /* PBXContainerItemProxy */ = { + 4ACEDA8CD45A31A11247F5802C9CD4CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 9E033EDB5EC0819481B0546434FA577B; + remoteGlobalIDString = DDAAFF9586B2A56E23A7293F173018C5; remoteInfo = AFNetworking; }; + CF4B1F6CCCB516B706B7BAB557DAA581 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 61F37D1986EB7BDE2FE1347CA0678FC4; + remoteInfo = YYCache; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0201E40A2EC35F788BD8A885100C12D3 /* libAFNetworking.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libAFNetworking.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 036FDD48539129C05AAE4C9ACA312100 /* UIWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIWebView+AFNetworking.h"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.h"; sourceTree = ""; }; - 0401DF9E61B17C3AE9FE93347CCD9E64 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; - 0E9837C7FFCFC4203B1BAADAADD8E206 /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; - 1207584E6BDCF4C846A1DDFE0BCFEECF /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; - 1246CB48952FF37C1DB54894C46F6390 /* AFAutoPurgingImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFAutoPurgingImageCache.m; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.m"; sourceTree = ""; }; - 12A9374C39A6EFA90AD3F2E64799ECC5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; - 14673F01BA2ED5D126E93E99A45B2088 /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; - 14F2B0D3DD13B76429F713F1F1A1CC6F /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; - 18A6CC7151721E485930D715056633ED /* AFAutoPurgingImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFAutoPurgingImageCache.h; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.h"; sourceTree = ""; }; - 18B9DCDB5BE79C17D786D046D23A6C8F /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; + 04179ADEB3E48D00177401CE2AE6D65A /* UIProgressView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIProgressView+AFNetworking.h"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.h"; sourceTree = ""; }; + 05F2E6593553C9A088B389782E4C21F6 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFSecurityPolicy.h; path = AFNetworking/AFSecurityPolicy.h; sourceTree = ""; }; + 0BE228D49C6209E9CFDAA7271061A3A8 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; + 0BE2F769751BDA3C5F239EC1610CDCA3 /* YYCache-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "YYCache-prefix.pch"; sourceTree = ""; }; + 1226405238B40DA0DDF7058EEB271945 /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; + 16CC9279D47341846F1F0C3E768E37B3 /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; + 190454DAF922532883BDAF1C9F40CC11 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + 198AC3304C840F87ED8DC9BCF0DE9F36 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; + 1B0CFEBD5CF113BAEF885005E1B20817 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; 1B84B129073C735F3F551986CD4C07BE /* Pods-XMNetworkingDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-XMNetworkingDemo-dummy.m"; sourceTree = ""; }; - 1E990D35FEF51D7420F303E35DCBE1F6 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; sourceTree = ""; }; - 20CB1302DD85B80CBADE42E436CF5930 /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; - 357FC25AA9F2E82213C986CE50969E1A /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; - 3B8C2F3F38AC8B05D07C9BAACD044EAD /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; - 42C03FCF30AB48A3B8DC805A289477E2 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; sourceTree = ""; }; - 42EAD270211F301E809EA7C39D05A3DC /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; + 1D37A8871B818EB31B57B46446EF8F5F /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "UIKit+AFNetworking/UIImage+AFNetworking.h"; sourceTree = ""; }; + 24247D459B43F22C1044FA8916DC38B4 /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; + 26EF6AA8212E60AFDE9EF12EAB1C3502 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFSecurityPolicy.m; path = AFNetworking/AFSecurityPolicy.m; sourceTree = ""; }; + 28E9A9AD2AC0A8BC2272B796F69C99EA /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; + 2A2478B976691B622F46FE62E02AD2FE /* AFImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFImageDownloader.m; path = "UIKit+AFNetworking/AFImageDownloader.m"; sourceTree = ""; }; + 2ED4D6CF9C87F1B0EBF2570B29F72D47 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLResponseSerialization.m; path = AFNetworking/AFURLResponseSerialization.m; sourceTree = ""; }; + 2FE42CB4E95256AAD8745E58C31DBE55 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkReachabilityManager.h; path = AFNetworking/AFNetworkReachabilityManager.h; sourceTree = ""; }; + 30AB58768F8C9A5F911BA6893F8B33A3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + 315AD1E90448E69479D38FC22293A41F /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImageView+AFNetworking.m"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.m"; sourceTree = ""; }; + 335C07088BD4F6ADB9489C618B1D5BF8 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFHTTPSessionManager.m; path = AFNetworking/AFHTTPSessionManager.m; sourceTree = ""; }; + 33EB56582E901F3F811B6C96E1D5EBCE /* YYMemoryCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYMemoryCache.m; path = YYCache/YYMemoryCache.m; sourceTree = ""; }; + 44F5891E4BCD119B26B6C6FE416E7CE2 /* YYKVStorage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYKVStorage.h; path = YYCache/YYKVStorage.h; sourceTree = ""; }; 45115CFB426155493B2DD8871CEA2E6E /* Pods-XMNetworkingDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-XMNetworkingDemo.release.xcconfig"; sourceTree = ""; }; - 4852ABEFD7FFFAE072C5835CCDB22279 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkReachabilityManager.m; path = AFNetworking/AFNetworkReachabilityManager.m; sourceTree = ""; }; - 4D925E789318555435D0DBEF9BEC8015 /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; - 51204DFB5BF601D556D71C3736263351 /* UIWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIWebView+AFNetworking.m"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.m"; sourceTree = ""; }; - 516F3F2A9B24B2E2092E84E8EAF0A9F7 /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; - 525066ED64B26EC45F9B2AD4D3B0D1B2 /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; - 78C774AEA3474BF09AD285C28E701D5F /* UIRefreshControl+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIRefreshControl+AFNetworking.h"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.h"; sourceTree = ""; }; + 49A3B5A7EC09B485BB64FFC5BAE15BA2 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; + 4B40D1BF112013A0EC9DA3DF93F7E496 /* AFImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFImageDownloader.h; path = "UIKit+AFNetworking/AFImageDownloader.h"; sourceTree = ""; }; + 4D695D934E10A7A6A543AFE0DC22731B /* UIButton+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIButton+AFNetworking.m"; path = "UIKit+AFNetworking/UIButton+AFNetworking.m"; sourceTree = ""; }; + 5A308217A0D49B581E696BB92EDE39B5 /* YYCache-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "YYCache-dummy.m"; sourceTree = ""; }; + 5E4EDF48A24DDB92B0D2F8F47CBF3992 /* YYDiskCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYDiskCache.m; path = YYCache/YYDiskCache.m; sourceTree = ""; }; + 5FB86D5093EB03A862C5463BEFDA8AB5 /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; + 5FCC3828D99C0750B59CE76BE103E097 /* YYCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYCache.m; path = YYCache/YYCache.m; sourceTree = ""; }; + 6681F556D8866BC59DA392801716A7E3 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFHTTPSessionManager.h; path = AFNetworking/AFHTTPSessionManager.h; sourceTree = ""; }; + 6B5B6C371805F7F75BD3C39A2787DE06 /* YYKVStorage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = YYKVStorage.m; path = YYCache/YYKVStorage.m; sourceTree = ""; }; 7BDEB0A1CDC6027BDF8930FF5467A4FD /* Pods-XMNetworkingDemo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-XMNetworkingDemo-frameworks.sh"; sourceTree = ""; }; 7C3E71920E88214D890FDA61B3284D52 /* Pods-XMNetworkingDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-XMNetworkingDemo.debug.xcconfig"; sourceTree = ""; }; - 8006E5A6F0951AA637FFA7F53DBA00D9 /* AFImageDownloader.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFImageDownloader.m; path = "UIKit+AFNetworking/AFImageDownloader.m"; sourceTree = ""; }; - 809E0EE6429DA2700D30D5F8F46F4100 /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; - 8946DE00AC08571F0D4A4F985A8FA609 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; - 8B17FF80B117EDDFBD41C5C3B5C1D217 /* AFImageDownloader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFImageDownloader.h; path = "UIKit+AFNetworking/AFImageDownloader.h"; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 808398E92D66F0AF181D527A6A2D44EC /* AFNetworking.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.xcconfig; sourceTree = ""; }; + 8A0B4CCC176F6AD325A29D6622B5738C /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; + 8B26183C6CF2FEDCC0C5DCD637E96BF3 /* libYYCache.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libYYCache.a; path = libYYCache.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 8B803F81AAA6B0FE5FD48B1C8156DC70 /* UIWebView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIWebView+AFNetworking.m"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.m"; sourceTree = ""; }; + 8BA9491ED4243D33B0A9307456D16183 /* UIActivityIndicatorView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIActivityIndicatorView+AFNetworking.m"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.m"; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 984423C823C40DF330BF6C4F0AD0492C /* YYCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYCache.h; path = YYCache/YYCache.h; sourceTree = ""; }; + 997BFFA88BC31074D829CCF307743591 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; + 9C20A2CD1FECDD9FF6D630B6B2730DC9 /* YYCache.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = YYCache.xcconfig; sourceTree = ""; }; + A0095B1DE3FF957383DE012EE95B5FD4 /* UIWebView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIWebView+AFNetworking.h"; path = "UIKit+AFNetworking/UIWebView+AFNetworking.h"; sourceTree = ""; }; + A0CF3695F745920B984D721E171552FB /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; + A3B9F0F74EF7E3F6AB63A81B46849E91 /* YYMemoryCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYMemoryCache.h; path = YYCache/YYMemoryCache.h; sourceTree = ""; }; + A43070D0130B6016EEC95897E9697256 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; A52B79635616E6B5651F49364B55D950 /* Pods-XMNetworkingDemo-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-XMNetworkingDemo-resources.sh"; sourceTree = ""; }; - A64716173FC0305057230E14CDCC7A77 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; - A7280C845CCA2804DEA9667377EE41CC /* libPods-XMNetworkingDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XMNetworkingDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - AFF2CC19E35B6A289DF5C325A6C2B4E7 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworkActivityIndicatorManager.h; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.h"; sourceTree = ""; }; - B9FDBCCB266ACFED93E55656FD8A014C /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; - BFD303D6F6C659A55A8684008D1476CB /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; - C0DC8653B61F64B5FC03BFC2B0A6E528 /* UIImage+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+AFNetworking.h"; path = "UIKit+AFNetworking/UIImage+AFNetworking.h"; sourceTree = ""; }; - C23C3983ADC1EBC0A6AD3D68F3DBC4BA /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImageView+AFNetworking.h"; path = "UIKit+AFNetworking/UIImageView+AFNetworking.h"; sourceTree = ""; }; - CC618B900858F4F77C2746363E77B86C /* UIRefreshControl+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIRefreshControl+AFNetworking.m"; path = "UIKit+AFNetworking/UIRefreshControl+AFNetworking.m"; sourceTree = ""; }; + ACD6D73DF3160687513B28C70CEF7111 /* AFCompatibilityMacros.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFCompatibilityMacros.h; path = AFNetworking/AFCompatibilityMacros.h; sourceTree = ""; }; + AD54A9E36C85A3B23F8994B420002CAD /* YYDiskCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = YYDiskCache.h; path = YYCache/YYDiskCache.h; sourceTree = ""; }; + B749E050B7F95CFDA2800E7065AAA454 /* AFAutoPurgingImageCache.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFAutoPurgingImageCache.m; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.m"; sourceTree = ""; }; + B8D39186E250DF2331FDD3EDAEBE05D2 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLResponseSerialization.h; path = AFNetworking/AFURLResponseSerialization.h; sourceTree = ""; }; + BFCFF8BCF5FDF94C2E5566CFF8820780 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; }; + C893579BAB23C4558D4A5E761AB00E1F /* UIButton+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIButton+AFNetworking.h"; path = "UIKit+AFNetworking/UIButton+AFNetworking.h"; sourceTree = ""; }; CE686B1FCD3CB847FE1D813AB531387F /* Pods-XMNetworkingDemo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-XMNetworkingDemo-acknowledgements.plist"; sourceTree = ""; }; - D0F90194E52430599383549278FEA918 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; - D1364E1A74FA884D5BCADB171DFE7353 /* AFNetworking.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = AFNetworking.xcconfig; sourceTree = ""; }; - D2792B01BCFFB8C68B0CE56421B99A2F /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLRequestSerialization.m; path = AFNetworking/AFURLRequestSerialization.m; sourceTree = ""; }; - E451FBBEE5D302A74D966AC502CE5B19 /* UIActivityIndicatorView+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIActivityIndicatorView+AFNetworking.h"; path = "UIKit+AFNetworking/UIActivityIndicatorView+AFNetworking.h"; sourceTree = ""; }; - E71FC5436C29FCEB72394E7117726B8F /* AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFNetworking.h; path = AFNetworking/AFNetworking.h; sourceTree = ""; }; - EC8A7C0B6179467051ED95E59DB2AF9F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; + D5C7DA2AE09D4E03472AEE872A4D0195 /* AFAutoPurgingImageCache.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFAutoPurgingImageCache.h; path = "UIKit+AFNetworking/AFAutoPurgingImageCache.h"; sourceTree = ""; }; + D988EE36AC007E295DF56FBDE2B81809 /* UIProgressView+AFNetworking.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIProgressView+AFNetworking.m"; path = "UIKit+AFNetworking/UIProgressView+AFNetworking.m"; sourceTree = ""; }; + DDF3DFD447607191A69D235243063BA7 /* AFURLSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFURLSessionManager.m; path = AFNetworking/AFURLSessionManager.m; sourceTree = ""; }; + DE8D49F6C924B4A658624C797CE7E3C5 /* AFNetworking-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "AFNetworking-prefix.pch"; sourceTree = ""; }; + DF61E6338A039FBCE54BFF53F13E877E /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLRequestSerialization.h; path = AFNetworking/AFURLRequestSerialization.h; sourceTree = ""; }; + E138C48D1DD85E6EF0F918FF39A71DDC /* libAFNetworking.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libAFNetworking.a; path = libAFNetworking.a; sourceTree = BUILT_PRODUCTS_DIR; }; + EA5B72AC7C85E91BF2F8C7382019721F /* AFNetworking-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "AFNetworking-dummy.m"; sourceTree = ""; }; + EFCD174CE3F5C08BCE83E19ABCED520F /* libPods-XMNetworkingDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-XMNetworkingDemo.a"; path = "libPods-XMNetworkingDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F06418D52F85291D487E2C732B183375 /* AFURLSessionManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = AFURLSessionManager.h; path = AFNetworking/AFURLSessionManager.h; sourceTree = ""; }; F3C94B8CA3B50C98B6D9C21E64980775 /* Pods-XMNetworkingDemo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-XMNetworkingDemo-acknowledgements.markdown"; sourceTree = ""; }; - F921D275AC6AA48C031BF91FD4592584 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - FE9DC137B1B02C802E7ABBECC9401A7B /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = AFNetworkActivityIndicatorManager.m; path = "UIKit+AFNetworking/AFNetworkActivityIndicatorManager.m"; sourceTree = ""; }; + FF1B46D89D554BA82A58F69AE273D1F5 /* UIKit+AFNetworking.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIKit+AFNetworking.h"; path = "UIKit+AFNetworking/UIKit+AFNetworking.h"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 110CA8F43678511966090BBFCC7384DE /* Frameworks */ = { + 7593EB39883BC66AFA102C60E008D5C0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0E642705E9D54540F88AF54A2EFA918F /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - F3284DBE3CA8932733932AD2A48445B2 /* Frameworks */ = { + 8756BB37F64AAC3AE16FAE90249207E3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CBCCEAD402645565401CA93924736979 /* CoreGraphics.framework in Frameworks */, - 0214246CCB1FF7182F7222B9CCDF8FCB /* Foundation.framework in Frameworks */, - F8DCA6C3C05A59B2C95A1B5F1CBD8C99 /* MobileCoreServices.framework in Frameworks */, - DE825B8F32AB823F4BE5492CAC6FCB4B /* Security.framework in Frameworks */, - 903158692A045396106CA22C0DD13BA6 /* SystemConfiguration.framework in Frameworks */, + 452FA80139D393F7212F57FC157E5A8E /* CoreGraphics.framework in Frameworks */, + 18A0969FF6EEC2C58A7D4D4AAB7C6060 /* MobileCoreServices.framework in Frameworks */, + FEDC1552CAE6D0410E6A27D827B0EF1B /* Security.framework in Frameworks */, + 7B6C0C29E2AC0F93F9C525BC89123049 /* SystemConfiguration.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 949459AADC3F0A7FE43DB0DCB46291B9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E5805C68A8E165853A7D91C10B9C1A89 /* CoreFoundation.framework in Frameworks */, + E3F841BB93F4B4AA90D24C99D397CFB8 /* QuartzCore.framework in Frameworks */, + 797A35DC27FF6FC03A1FCE70C458E47F /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0336952400392A094D9CF93F23FBA803 /* Reachability */ = { - isa = PBXGroup; - children = ( - 357FC25AA9F2E82213C986CE50969E1A /* AFNetworkReachabilityManager.h */, - 4852ABEFD7FFFAE072C5835CCDB22279 /* AFNetworkReachabilityManager.m */, - ); - name = Reachability; - sourceTree = ""; - }; - 118C018DD63A7C9B85C796B9D7927B72 /* Serialization */ = { - isa = PBXGroup; - children = ( - 18B9DCDB5BE79C17D786D046D23A6C8F /* AFURLRequestSerialization.h */, - D2792B01BCFFB8C68B0CE56421B99A2F /* AFURLRequestSerialization.m */, - 8946DE00AC08571F0D4A4F985A8FA609 /* AFURLResponseSerialization.h */, - 1E990D35FEF51D7420F303E35DCBE1F6 /* AFURLResponseSerialization.m */, - ); - name = Serialization; - sourceTree = ""; - }; - 1C26585A924F80DB59965DD3B7AB0AD1 /* NSURLSession */ = { + 1D605E3734373A8AC4E2F82571C927FE /* iOS */ = { isa = PBXGroup; children = ( - 42C03FCF30AB48A3B8DC805A289477E2 /* AFHTTPSessionManager.h */, - 42EAD270211F301E809EA7C39D05A3DC /* AFHTTPSessionManager.m */, - 525066ED64B26EC45F9B2AD4D3B0D1B2 /* AFURLSessionManager.h */, - 809E0EE6429DA2700D30D5F8F46F4100 /* AFURLSessionManager.m */, + A43070D0130B6016EEC95897E9697256 /* CoreFoundation.framework */, + BFCFF8BCF5FDF94C2E5566CFF8820780 /* CoreGraphics.framework */, + 1B0CFEBD5CF113BAEF885005E1B20817 /* MobileCoreServices.framework */, + 49A3B5A7EC09B485BB64FFC5BAE15BA2 /* QuartzCore.framework */, + A0CF3695F745920B984D721E171552FB /* Security.framework */, + 190454DAF922532883BDAF1C9F40CC11 /* SystemConfiguration.framework */, + 30AB58768F8C9A5F911BA6893F8B33A3 /* UIKit.framework */, ); - name = NSURLSession; - sourceTree = ""; - }; - 20B56609144CE204DFA8221F742B2D76 /* Frameworks */ = { - isa = PBXGroup; - children = ( - CB79318D3E8AF2183319FF8098C5AE5E /* iOS */, - ); - name = Frameworks; + name = iOS; sourceTree = ""; }; - 2C186AA24E2640F4BC841D3813B8BAE7 /* Support Files */ = { + 24C6681C0183378F9034CE790B10359E /* Support Files */ = { isa = PBXGroup; children = ( - D1364E1A74FA884D5BCADB171DFE7353 /* AFNetworking.xcconfig */, - 14F2B0D3DD13B76429F713F1F1A1CC6F /* AFNetworking-dummy.m */, - 14673F01BA2ED5D126E93E99A45B2088 /* AFNetworking-prefix.pch */, + 808398E92D66F0AF181D527A6A2D44EC /* AFNetworking.xcconfig */, + EA5B72AC7C85E91BF2F8C7382019721F /* AFNetworking-dummy.m */, + DE8D49F6C924B4A658624C797CE7E3C5 /* AFNetworking-prefix.pch */, ); name = "Support Files"; path = "../Target Support Files/AFNetworking"; @@ -196,6 +212,15 @@ name = "Targets Support Files"; sourceTree = ""; }; + 2FD34BD87DC22D42638F2FB053D11B4F /* Pods */ = { + isa = PBXGroup; + children = ( + F7E990C0FB04D9560ECBD4A76EE2E4DE /* AFNetworking */, + FBEEF643F88F75A42500A4B2E160FD6B /* YYCache */, + ); + name = Pods; + sourceTree = ""; + }; 4419A764040CDFF177364FC4F9CD6E9A /* Pods-XMNetworkingDemo */ = { isa = PBXGroup; children = ( @@ -211,159 +236,239 @@ path = "Target Support Files/Pods-XMNetworkingDemo"; sourceTree = ""; }; - 641BDD347DE7B8BB81D6CA5727C6EC5A /* Pods */ = { + 57844F395989F62A75B441AC674E8146 /* Products */ = { isa = PBXGroup; children = ( - D8AEA08F300093373DE87ADAC55F71FA /* AFNetworking */, + E138C48D1DD85E6EF0F918FF39A71DDC /* libAFNetworking.a */, + EFCD174CE3F5C08BCE83E19ABCED520F /* libPods-XMNetworkingDemo.a */, + 8B26183C6CF2FEDCC0C5DCD637E96BF3 /* libYYCache.a */, ); - name = Pods; + name = Products; sourceTree = ""; }; - 64B71C384435C48FAA2EDD45AEDAF210 /* UIKit */ = { + 745DD48C71D4776CB875DE70FDB9CFE7 /* Security */ = { isa = PBXGroup; children = ( - 18A6CC7151721E485930D715056633ED /* AFAutoPurgingImageCache.h */, - 1246CB48952FF37C1DB54894C46F6390 /* AFAutoPurgingImageCache.m */, - 8B17FF80B117EDDFBD41C5C3B5C1D217 /* AFImageDownloader.h */, - 8006E5A6F0951AA637FFA7F53DBA00D9 /* AFImageDownloader.m */, - AFF2CC19E35B6A289DF5C325A6C2B4E7 /* AFNetworkActivityIndicatorManager.h */, - FE9DC137B1B02C802E7ABBECC9401A7B /* AFNetworkActivityIndicatorManager.m */, - E451FBBEE5D302A74D966AC502CE5B19 /* UIActivityIndicatorView+AFNetworking.h */, - 4D925E789318555435D0DBEF9BEC8015 /* UIActivityIndicatorView+AFNetworking.m */, - BFD303D6F6C659A55A8684008D1476CB /* UIButton+AFNetworking.h */, - 516F3F2A9B24B2E2092E84E8EAF0A9F7 /* UIButton+AFNetworking.m */, - C0DC8653B61F64B5FC03BFC2B0A6E528 /* UIImage+AFNetworking.h */, - C23C3983ADC1EBC0A6AD3D68F3DBC4BA /* UIImageView+AFNetworking.h */, - 0E9837C7FFCFC4203B1BAADAADD8E206 /* UIImageView+AFNetworking.m */, - 20CB1302DD85B80CBADE42E436CF5930 /* UIKit+AFNetworking.h */, - 1207584E6BDCF4C846A1DDFE0BCFEECF /* UIProgressView+AFNetworking.h */, - D0F90194E52430599383549278FEA918 /* UIProgressView+AFNetworking.m */, - 78C774AEA3474BF09AD285C28E701D5F /* UIRefreshControl+AFNetworking.h */, - CC618B900858F4F77C2746363E77B86C /* UIRefreshControl+AFNetworking.m */, - 036FDD48539129C05AAE4C9ACA312100 /* UIWebView+AFNetworking.h */, - 51204DFB5BF601D556D71C3736263351 /* UIWebView+AFNetworking.m */, + 05F2E6593553C9A088B389782E4C21F6 /* AFSecurityPolicy.h */, + 26EF6AA8212E60AFDE9EF12EAB1C3502 /* AFSecurityPolicy.m */, ); - name = UIKit; + name = Security; sourceTree = ""; }; 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 20B56609144CE204DFA8221F742B2D76 /* Frameworks */, - 641BDD347DE7B8BB81D6CA5727C6EC5A /* Pods */, - 9D3ECD3316029EEDD6E224365DFE203B /* Products */, + F4CDA5FA9197A41E0081E84F932906EB /* Frameworks */, + 2FD34BD87DC22D42638F2FB053D11B4F /* Pods */, + 57844F395989F62A75B441AC674E8146 /* Products */, 2CA0883CD03146E6AD022CB31BAB9C31 /* Targets Support Files */, ); sourceTree = ""; }; - 9D3ECD3316029EEDD6E224365DFE203B /* Products */ = { + 7F979E2F6ACA8CFCF2F9084DF68480C1 /* UIKit */ = { isa = PBXGroup; children = ( - 0201E40A2EC35F788BD8A885100C12D3 /* libAFNetworking.a */, - A7280C845CCA2804DEA9667377EE41CC /* libPods-XMNetworkingDemo.a */, + D5C7DA2AE09D4E03472AEE872A4D0195 /* AFAutoPurgingImageCache.h */, + B749E050B7F95CFDA2800E7065AAA454 /* AFAutoPurgingImageCache.m */, + 4B40D1BF112013A0EC9DA3DF93F7E496 /* AFImageDownloader.h */, + 2A2478B976691B622F46FE62E02AD2FE /* AFImageDownloader.m */, + 997BFFA88BC31074D829CCF307743591 /* AFNetworkActivityIndicatorManager.h */, + 28E9A9AD2AC0A8BC2272B796F69C99EA /* AFNetworkActivityIndicatorManager.m */, + 16CC9279D47341846F1F0C3E768E37B3 /* UIActivityIndicatorView+AFNetworking.h */, + 8BA9491ED4243D33B0A9307456D16183 /* UIActivityIndicatorView+AFNetworking.m */, + C893579BAB23C4558D4A5E761AB00E1F /* UIButton+AFNetworking.h */, + 4D695D934E10A7A6A543AFE0DC22731B /* UIButton+AFNetworking.m */, + 1D37A8871B818EB31B57B46446EF8F5F /* UIImage+AFNetworking.h */, + 24247D459B43F22C1044FA8916DC38B4 /* UIImageView+AFNetworking.h */, + 315AD1E90448E69479D38FC22293A41F /* UIImageView+AFNetworking.m */, + FF1B46D89D554BA82A58F69AE273D1F5 /* UIKit+AFNetworking.h */, + 04179ADEB3E48D00177401CE2AE6D65A /* UIProgressView+AFNetworking.h */, + D988EE36AC007E295DF56FBDE2B81809 /* UIProgressView+AFNetworking.m */, + 1226405238B40DA0DDF7058EEB271945 /* UIRefreshControl+AFNetworking.h */, + 8A0B4CCC176F6AD325A29D6622B5738C /* UIRefreshControl+AFNetworking.m */, + A0095B1DE3FF957383DE012EE95B5FD4 /* UIWebView+AFNetworking.h */, + 8B803F81AAA6B0FE5FD48B1C8156DC70 /* UIWebView+AFNetworking.m */, ); - name = Products; + name = UIKit; sourceTree = ""; }; - CB79318D3E8AF2183319FF8098C5AE5E /* iOS */ = { + 97B3DC4DDB6C4FD6B66CB7D02CE7F10C /* Serialization */ = { isa = PBXGroup; children = ( - A64716173FC0305057230E14CDCC7A77 /* CoreGraphics.framework */, - F921D275AC6AA48C031BF91FD4592584 /* Foundation.framework */, - B9FDBCCB266ACFED93E55656FD8A014C /* MobileCoreServices.framework */, - 12A9374C39A6EFA90AD3F2E64799ECC5 /* Security.framework */, - EC8A7C0B6179467051ED95E59DB2AF9F /* SystemConfiguration.framework */, + DF61E6338A039FBCE54BFF53F13E877E /* AFURLRequestSerialization.h */, + 0BE228D49C6209E9CFDAA7271061A3A8 /* AFURLRequestSerialization.m */, + B8D39186E250DF2331FDD3EDAEBE05D2 /* AFURLResponseSerialization.h */, + 2ED4D6CF9C87F1B0EBF2570B29F72D47 /* AFURLResponseSerialization.m */, ); - name = iOS; + name = Serialization; sourceTree = ""; }; - D8AEA08F300093373DE87ADAC55F71FA /* AFNetworking */ = { + A7C26D5EB5F234F9619B74D7D6B3BF76 /* Support Files */ = { isa = PBXGroup; children = ( - E71FC5436C29FCEB72394E7117726B8F /* AFNetworking.h */, - 1C26585A924F80DB59965DD3B7AB0AD1 /* NSURLSession */, - 0336952400392A094D9CF93F23FBA803 /* Reachability */, - E9A2D2E704D5128BD90065AA48D6522C /* Security */, - 118C018DD63A7C9B85C796B9D7927B72 /* Serialization */, - 2C186AA24E2640F4BC841D3813B8BAE7 /* Support Files */, - 64B71C384435C48FAA2EDD45AEDAF210 /* UIKit */, + 9C20A2CD1FECDD9FF6D630B6B2730DC9 /* YYCache.xcconfig */, + 5A308217A0D49B581E696BB92EDE39B5 /* YYCache-dummy.m */, + 0BE2F769751BDA3C5F239EC1610CDCA3 /* YYCache-prefix.pch */, ); + name = "Support Files"; + path = "../Target Support Files/YYCache"; + sourceTree = ""; + }; + D182555B551CA293582C16EC5EFD3AB3 /* Reachability */ = { + isa = PBXGroup; + children = ( + 2FE42CB4E95256AAD8745E58C31DBE55 /* AFNetworkReachabilityManager.h */, + 198AC3304C840F87ED8DC9BCF0DE9F36 /* AFNetworkReachabilityManager.m */, + ); + name = Reachability; + sourceTree = ""; + }; + DDF848B1415BE982F93E626939F0B810 /* NSURLSession */ = { + isa = PBXGroup; + children = ( + ACD6D73DF3160687513B28C70CEF7111 /* AFCompatibilityMacros.h */, + 6681F556D8866BC59DA392801716A7E3 /* AFHTTPSessionManager.h */, + 335C07088BD4F6ADB9489C618B1D5BF8 /* AFHTTPSessionManager.m */, + F06418D52F85291D487E2C732B183375 /* AFURLSessionManager.h */, + DDF3DFD447607191A69D235243063BA7 /* AFURLSessionManager.m */, + ); + name = NSURLSession; + sourceTree = ""; + }; + F4CDA5FA9197A41E0081E84F932906EB /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1D605E3734373A8AC4E2F82571C927FE /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + F7E990C0FB04D9560ECBD4A76EE2E4DE /* AFNetworking */ = { + isa = PBXGroup; + children = ( + 5FB86D5093EB03A862C5463BEFDA8AB5 /* AFNetworking.h */, + DDF848B1415BE982F93E626939F0B810 /* NSURLSession */, + D182555B551CA293582C16EC5EFD3AB3 /* Reachability */, + 745DD48C71D4776CB875DE70FDB9CFE7 /* Security */, + 97B3DC4DDB6C4FD6B66CB7D02CE7F10C /* Serialization */, + 24C6681C0183378F9034CE790B10359E /* Support Files */, + 7F979E2F6ACA8CFCF2F9084DF68480C1 /* UIKit */, + ); + name = AFNetworking; path = AFNetworking; sourceTree = ""; }; - E9A2D2E704D5128BD90065AA48D6522C /* Security */ = { + FBEEF643F88F75A42500A4B2E160FD6B /* YYCache */ = { isa = PBXGroup; children = ( - 0401DF9E61B17C3AE9FE93347CCD9E64 /* AFSecurityPolicy.h */, - 3B8C2F3F38AC8B05D07C9BAACD044EAD /* AFSecurityPolicy.m */, + 984423C823C40DF330BF6C4F0AD0492C /* YYCache.h */, + 5FCC3828D99C0750B59CE76BE103E097 /* YYCache.m */, + AD54A9E36C85A3B23F8994B420002CAD /* YYDiskCache.h */, + 5E4EDF48A24DDB92B0D2F8F47CBF3992 /* YYDiskCache.m */, + 44F5891E4BCD119B26B6C6FE416E7CE2 /* YYKVStorage.h */, + 6B5B6C371805F7F75BD3C39A2787DE06 /* YYKVStorage.m */, + A3B9F0F74EF7E3F6AB63A81B46849E91 /* YYMemoryCache.h */, + 33EB56582E901F3F811B6C96E1D5EBCE /* YYMemoryCache.m */, + A7C26D5EB5F234F9619B74D7D6B3BF76 /* Support Files */, ); - name = Security; + name = YYCache; + path = YYCache; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 0A1C2B07813030B0D51EB1D804A4439E /* Headers */ = { + 4417300C0CF3155561390EFA84D6AB86 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + DB11D96468F2FB045746DB2DC9EC878A /* AFAutoPurgingImageCache.h in Headers */, + 6B5E29AF5CC52D74BF3101BC7E2C59A1 /* AFCompatibilityMacros.h in Headers */, + AB5E0668ECE58C8965EACB5078BA644A /* AFHTTPSessionManager.h in Headers */, + 97ACF1603BEF20B66F0058CCF0AE05B2 /* AFImageDownloader.h in Headers */, + D2BF2A30F845978BD2257306C0A0F4F4 /* AFNetworkActivityIndicatorManager.h in Headers */, + 65F56DD218227209F7AFCF2A15EDCE2D /* AFNetworking.h in Headers */, + 9272085131E5B9072B7C0F4B21008A6D /* AFNetworkReachabilityManager.h in Headers */, + CAFC9622F9174BACE6787BC24E3E4444 /* AFSecurityPolicy.h in Headers */, + C973E131940932D82E6B18C79BDE6AFF /* AFURLRequestSerialization.h in Headers */, + 3BE2B8DF14E40C80FD77000DFF97E1F2 /* AFURLResponseSerialization.h in Headers */, + E28D315C00C8F9CD7D3A4887E94D6DAA /* AFURLSessionManager.h in Headers */, + C1D7647AD60CE3CCD9D86B030A36E442 /* UIActivityIndicatorView+AFNetworking.h in Headers */, + EC6F67D55D8FCDF3F76FF6D16A491BF7 /* UIButton+AFNetworking.h in Headers */, + 4AB16F37F3DB310D29874942A952568B /* UIImage+AFNetworking.h in Headers */, + 26873CE294135E7F21A809C79C117DEB /* UIImageView+AFNetworking.h in Headers */, + 394685034942F5FA49C1E8A0CCFD93F9 /* UIKit+AFNetworking.h in Headers */, + 8BFDD24EA734D85A262AAE9A3AA33222 /* UIProgressView+AFNetworking.h in Headers */, + 381B7AE4D90DB87F384B22E7C1540901 /* UIRefreshControl+AFNetworking.h in Headers */, + EC04F2F828BAADBAB9FA13518F1F2EE7 /* UIWebView+AFNetworking.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 76A59604A8CA7F829D0FC46978BDFB89 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 17889562A613EFB9E8C0CD14947CCC8F /* AFAutoPurgingImageCache.h in Headers */, - E66EDE92DE4B13E4853191475509CDFB /* AFHTTPSessionManager.h in Headers */, - 945F691AD18DC2361A75C6621E42461C /* AFImageDownloader.h in Headers */, - 1702DB74CC573578862AA584FC9D1632 /* AFNetworkActivityIndicatorManager.h in Headers */, - C60E5845068B90D7760411CE582C2934 /* AFNetworking.h in Headers */, - FC0BDC904394B55C2E9C3A8C308E8EB6 /* AFNetworkReachabilityManager.h in Headers */, - 75D4D1F473F6DA208001A46179BAEB7A /* AFSecurityPolicy.h in Headers */, - 5D437F5C4A12A4552070DCFCC423583B /* AFURLRequestSerialization.h in Headers */, - EDEDABB0A7CE2131C2CF03E094C1840D /* AFURLResponseSerialization.h in Headers */, - 29D221887670387A248AD92AA94253C2 /* AFURLSessionManager.h in Headers */, - AFC6DC1967B85742B8ECA969CED51610 /* UIActivityIndicatorView+AFNetworking.h in Headers */, - B3B907CDAF7FDC60BFE105DDB4B51B6A /* UIButton+AFNetworking.h in Headers */, - D542E74CF3A429E7433464C12405F07B /* UIImage+AFNetworking.h in Headers */, - 8962061859D3579C36C4703E96D8F3FD /* UIImageView+AFNetworking.h in Headers */, - B43CDF265CF01D7C6072082897C51DEE /* UIKit+AFNetworking.h in Headers */, - 7482DD9AE507E2E744A01F061D7C9266 /* UIProgressView+AFNetworking.h in Headers */, - F4AF1BA06F07E566D12446F8AB86C929 /* UIRefreshControl+AFNetworking.h in Headers */, - 63FF4EC1D3DDA4B5ED2F68BFC306B2BF /* UIWebView+AFNetworking.h in Headers */, + 7B93B208696C809BDB323361C138A900 /* YYCache.h in Headers */, + F48BF55BC20DB817E7F3BB82F939E6D6 /* YYDiskCache.h in Headers */, + 4491C6FB6EDAAF0D5EE72D84FC7FD902 /* YYKVStorage.h in Headers */, + 5D925CF6BBFA9010A254C57AAA9FB9B1 /* YYMemoryCache.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 9E033EDB5EC0819481B0546434FA577B /* AFNetworking */ = { + 61F37D1986EB7BDE2FE1347CA0678FC4 /* YYCache */ = { isa = PBXNativeTarget; - buildConfigurationList = 483FBC4A668BF7F1A8767452E7E188AC /* Build configuration list for PBXNativeTarget "AFNetworking" */; + buildConfigurationList = 3F1FD9F068F4F3099D38450DD50B3C54 /* Build configuration list for PBXNativeTarget "YYCache" */; buildPhases = ( - AAEE4C1DF970D446DF57CA3DDD16AD00 /* Sources */, - F3284DBE3CA8932733932AD2A48445B2 /* Frameworks */, - 0A1C2B07813030B0D51EB1D804A4439E /* Headers */, + 8802282BBCAB419E2FF495B02EED7C24 /* Sources */, + 949459AADC3F0A7FE43DB0DCB46291B9 /* Frameworks */, + 76A59604A8CA7F829D0FC46978BDFB89 /* Headers */, ); buildRules = ( ); dependencies = ( ); - name = AFNetworking; - productName = AFNetworking; - productReference = 0201E40A2EC35F788BD8A885100C12D3 /* libAFNetworking.a */; + name = YYCache; + productName = YYCache; + productReference = 8B26183C6CF2FEDCC0C5DCD637E96BF3 /* libYYCache.a */; productType = "com.apple.product-type.library.static"; }; - D16A3DF7673CE2A2EA1ACE9861DF4F7F /* Pods-XMNetworkingDemo */ = { + A8C079558AC09E554F11F2BAF1F8D591 /* Pods-XMNetworkingDemo */ = { isa = PBXNativeTarget; - buildConfigurationList = BD6EEA93F7F93FE28AF31408FC35FF32 /* Build configuration list for PBXNativeTarget "Pods-XMNetworkingDemo" */; + buildConfigurationList = BC2A3E579DA0BE99A14F4C4FEAECFD44 /* Build configuration list for PBXNativeTarget "Pods-XMNetworkingDemo" */; buildPhases = ( - 9EBE171EDDF4CBE2943E73CADD6686A1 /* Sources */, - 110CA8F43678511966090BBFCC7384DE /* Frameworks */, + BDC277A64D56DDD0C7D3F002F3887489 /* Sources */, + 7593EB39883BC66AFA102C60E008D5C0 /* Frameworks */, ); buildRules = ( ); dependencies = ( - BD4BADD079B97D27B16DD6DEFFC35C34 /* PBXTargetDependency */, + 8CA4399ACF7DF8AA03C034D98FA00E37 /* PBXTargetDependency */, + 51992DB0B8B57F64DCC3D4C516032B4E /* PBXTargetDependency */, ); name = "Pods-XMNetworkingDemo"; productName = "Pods-XMNetworkingDemo"; - productReference = A7280C845CCA2804DEA9667377EE41CC /* libPods-XMNetworkingDemo.a */; + productReference = EFCD174CE3F5C08BCE83E19ABCED520F /* libPods-XMNetworkingDemo.a */; + productType = "com.apple.product-type.library.static"; + }; + DDAAFF9586B2A56E23A7293F173018C5 /* AFNetworking */ = { + isa = PBXNativeTarget; + buildConfigurationList = 50BC50B372A9590F37BAD61CD86E2964 /* Build configuration list for PBXNativeTarget "AFNetworking" */; + buildPhases = ( + 1B9807F0815BF3A33A7F1A79F2AD1E75 /* Sources */, + 8756BB37F64AAC3AE16FAE90249207E3 /* Frameworks */, + 4417300C0CF3155561390EFA84D6AB86 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AFNetworking; + productName = AFNetworking; + productReference = E138C48D1DD85E6EF0F918FF39A71DDC /* libAFNetworking.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ @@ -383,56 +488,75 @@ en, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; - productRefGroup = 9D3ECD3316029EEDD6E224365DFE203B /* Products */; + productRefGroup = 57844F395989F62A75B441AC674E8146 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 9E033EDB5EC0819481B0546434FA577B /* AFNetworking */, - D16A3DF7673CE2A2EA1ACE9861DF4F7F /* Pods-XMNetworkingDemo */, + DDAAFF9586B2A56E23A7293F173018C5 /* AFNetworking */, + A8C079558AC09E554F11F2BAF1F8D591 /* Pods-XMNetworkingDemo */, + 61F37D1986EB7BDE2FE1347CA0678FC4 /* YYCache */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - 9EBE171EDDF4CBE2943E73CADD6686A1 /* Sources */ = { + 1B9807F0815BF3A33A7F1A79F2AD1E75 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 2E093B774E17FC557A5815F454077404 /* Pods-XMNetworkingDemo-dummy.m in Sources */, + 82640F9EE0076F032567A8C1E3EDDA82 /* AFAutoPurgingImageCache.m in Sources */, + 302888D10A449158C46614ABA5B42B22 /* AFHTTPSessionManager.m in Sources */, + 456F377DD03B42CFD65943C1347E0940 /* AFImageDownloader.m in Sources */, + DE737B5DADB0D0FF1E6029228BF393FA /* AFNetworkActivityIndicatorManager.m in Sources */, + 67CC31341F522E0D3F13A0411613DE92 /* AFNetworking-dummy.m in Sources */, + 68E1B2F45F100C41D956371BABA541B7 /* AFNetworkReachabilityManager.m in Sources */, + 2753EF5BCBEC5A53CC7115842D69A226 /* AFSecurityPolicy.m in Sources */, + C71CCE388FB703FD7EB6B82D56B959AF /* AFURLRequestSerialization.m in Sources */, + 2C67FD363E5EFED189C3F8277F6B1F1F /* AFURLResponseSerialization.m in Sources */, + 2633BE2E887BB96BEB21584B65131AF8 /* AFURLSessionManager.m in Sources */, + 3334746D072810854256D338A2AB0C0D /* UIActivityIndicatorView+AFNetworking.m in Sources */, + 444C42DCE893C47FC935496EB2CD4A17 /* UIButton+AFNetworking.m in Sources */, + 6913AF9BFAD48198FAC591BE7759B842 /* UIImageView+AFNetworking.m in Sources */, + A9F1387B1C0A79677DDC636B8F9E6517 /* UIProgressView+AFNetworking.m in Sources */, + 9B5B00119CD6F9D1A88FA33EA3931116 /* UIRefreshControl+AFNetworking.m in Sources */, + 4D203CC08A98E696BDCD6A3578C5DA1B /* UIWebView+AFNetworking.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - AAEE4C1DF970D446DF57CA3DDD16AD00 /* Sources */ = { + 8802282BBCAB419E2FF495B02EED7C24 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A906A376A93C1C83BB89E8F63A663F43 /* AFAutoPurgingImageCache.m in Sources */, - E81A3DDBBA7965126D98EEA4C35E7363 /* AFHTTPSessionManager.m in Sources */, - 211646AEE68A3577495B0DF917A0DCDC /* AFImageDownloader.m in Sources */, - F8B71BB9667E21385D7AAEFEC796BAE4 /* AFNetworkActivityIndicatorManager.m in Sources */, - 63299DE5DEA29075FADA35711169188E /* AFNetworking-dummy.m in Sources */, - 19CFCF718B674B91847980FA20429558 /* AFNetworkReachabilityManager.m in Sources */, - 0A1CE7CE58B28609B573D4058ABDD616 /* AFSecurityPolicy.m in Sources */, - FB9AA5207284E33FFC55FEB308BFA71F /* AFURLRequestSerialization.m in Sources */, - C4D12D56B5E4323CDE6A77AEF30D4D9F /* AFURLResponseSerialization.m in Sources */, - 064EC4AA8FCCD08F2037037B1E672DBF /* AFURLSessionManager.m in Sources */, - 7B12269BEFA5305C78EC3D22AB2B1CEC /* UIActivityIndicatorView+AFNetworking.m in Sources */, - 2612D2B9BEA56B8CB2B361AA0BAB599F /* UIButton+AFNetworking.m in Sources */, - 2BCD3F861A5F4CF448072C4692AD130D /* UIImageView+AFNetworking.m in Sources */, - D486C538AE3151018303619712539B4C /* UIProgressView+AFNetworking.m in Sources */, - 12FCB056A2B7051B0D91B16CAFE85C1D /* UIRefreshControl+AFNetworking.m in Sources */, - 17E74D623462991F19748A7F99CF8ED6 /* UIWebView+AFNetworking.m in Sources */, + A8EEBDE76CBA2183583E6E49B176A3C4 /* YYCache-dummy.m in Sources */, + 3394570B7C6385D92DDEDEC22D2BB9DE /* YYCache.m in Sources */, + 9C979E541C3F371E7CF1A8E1B64D45AF /* YYDiskCache.m in Sources */, + 75D068B7AEF4C2B0CBA6E640C37CD041 /* YYKVStorage.m in Sources */, + 4454F5B3AFC67E6A741186DD20859313 /* YYMemoryCache.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + BDC277A64D56DDD0C7D3F002F3887489 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 159B47380CE1D5B8F6210E9D635DA7A0 /* Pods-XMNetworkingDemo-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - BD4BADD079B97D27B16DD6DEFFC35C34 /* PBXTargetDependency */ = { + 51992DB0B8B57F64DCC3D4C516032B4E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = YYCache; + target = 61F37D1986EB7BDE2FE1347CA0678FC4 /* YYCache */; + targetProxy = CF4B1F6CCCB516B706B7BAB557DAA581 /* PBXContainerItemProxy */; + }; + 8CA4399ACF7DF8AA03C034D98FA00E37 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = AFNetworking; - target = 9E033EDB5EC0819481B0546434FA577B /* AFNetworking */; - targetProxy = B8362C42B85B9FF74CFC6AF08A7143EF /* PBXContainerItemProxy */; + target = DDAAFF9586B2A56E23A7293F173018C5 /* AFNetworking */; + targetProxy = 4ACEDA8CD45A31A11247F5802C9CD4CC /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -500,16 +624,38 @@ }; name = Debug; }; - 2946D24682D665FA8DB64B5E6F799787 /* Debug */ = { + 524C34452152DCFB151E600D63A0ECFE /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D1364E1A74FA884D5BCADB171DFE7353 /* AFNetworking.xcconfig */; + baseConfigurationReference = 45115CFB426155493B2DD8871CEA2E6E /* Pods-XMNetworkingDemo.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MACH_O_TYPE = staticlib; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 527311EFF76C9BB5B60C670211ECDD37 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 808398E92D66F0AF181D527A6A2D44EC /* AFNetworking.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PRIVATE_HEADERS_FOLDER_PATH = ""; @@ -520,12 +666,13 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; }; - name = Debug; + name = Release; }; - B80E1ECBDEFC9B7FAA49CA7B0BFCA360 /* Release */ = { + 7390A9CE6B3CDBDF1936BA01F814905D /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 45115CFB426155493B2DD8871CEA2E6E /* Pods-XMNetworkingDemo.release.xcconfig */; + baseConfigurationReference = 7C3E71920E88214D890FDA61B3284D52 /* Pods-XMNetworkingDemo.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; @@ -541,25 +688,47 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; }; - name = Release; + name = Debug; }; - C3601C47E18C0AE6EC866511CF8ADFAD /* Release */ = { + 9B04726E42983064E524767C48797A93 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D1364E1A74FA884D5BCADB171DFE7353 /* AFNetworking.xcconfig */; + baseConfigurationReference = 9C20A2CD1FECDD9FF6D630B6B2730DC9 /* YYCache.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + GCC_PREFIX_HEADER = "Target Support Files/YYCache/YYCache-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PRIVATE_HEADERS_FOLDER_PATH = ""; - PRODUCT_MODULE_NAME = AFNetworking; - PRODUCT_NAME = AFNetworking; + PRODUCT_MODULE_NAME = YYCache; + PRODUCT_NAME = YYCache; + PUBLIC_HEADERS_FOLDER_PATH = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + CEBF16EBFF297E99D686C4044B422743 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9C20A2CD1FECDD9FF6D630B6B2730DC9 /* YYCache.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + GCC_PREFIX_HEADER = "Target Support Files/YYCache/YYCache-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 6.0; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = YYCache; + PRODUCT_NAME = YYCache; PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; @@ -569,23 +738,25 @@ }; name = Release; }; - CA1D4BB941C8A57A8D5504BC89BD4336 /* Debug */ = { + EBC4D7F324D89E6010B31CCFAB573A97 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7C3E71920E88214D890FDA61B3284D52 /* Pods-XMNetworkingDemo.debug.xcconfig */; + baseConfigurationReference = 808398E92D66F0AF181D527A6A2D44EC /* AFNetworking.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACH_O_TYPE = staticlib; + GCC_PREFIX_HEADER = "Target Support Files/AFNetworking/AFNetworking-prefix.pch"; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRIVATE_HEADERS_FOLDER_PATH = ""; + PRODUCT_MODULE_NAME = AFNetworking; + PRODUCT_NAME = AFNetworking; + PUBLIC_HEADERS_FOLDER_PATH = ""; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -660,20 +831,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 483FBC4A668BF7F1A8767452E7E188AC /* Build configuration list for PBXNativeTarget "AFNetworking" */ = { + 3F1FD9F068F4F3099D38450DD50B3C54 /* Build configuration list for PBXNativeTarget "YYCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B04726E42983064E524767C48797A93 /* Debug */, + CEBF16EBFF297E99D686C4044B422743 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 50BC50B372A9590F37BAD61CD86E2964 /* Build configuration list for PBXNativeTarget "AFNetworking" */ = { isa = XCConfigurationList; buildConfigurations = ( - 2946D24682D665FA8DB64B5E6F799787 /* Debug */, - C3601C47E18C0AE6EC866511CF8ADFAD /* Release */, + EBC4D7F324D89E6010B31CCFAB573A97 /* Debug */, + 527311EFF76C9BB5B60C670211ECDD37 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - BD6EEA93F7F93FE28AF31408FC35FF32 /* Build configuration list for PBXNativeTarget "Pods-XMNetworkingDemo" */ = { + BC2A3E579DA0BE99A14F4C4FEAECFD44 /* Build configuration list for PBXNativeTarget "Pods-XMNetworkingDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - CA1D4BB941C8A57A8D5504BC89BD4336 /* Debug */, - B80E1ECBDEFC9B7FAA49CA7B0BFCA360 /* Release */, + 7390A9CE6B3CDBDF1936BA01F814905D /* Debug */, + 524C34452152DCFB151E600D63A0ECFE /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.markdown b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.markdown index 9470436b..814fe587 100644 --- a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.markdown +++ b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.markdown @@ -23,4 +23,30 @@ 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 + +The MIT License (MIT) + +Copyright (c) 2015 ibireme + +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. + + Generated by CocoaPods - https://cocoapods.org diff --git a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.plist b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.plist index c13117b2..a1cbcf2b 100644 --- a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.plist +++ b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-acknowledgements.plist @@ -41,6 +41,38 @@ THE SOFTWARE. Type PSGroupSpecifier + + FooterText + 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. + + + License + MIT + Title + YYCache + Type + PSGroupSpecifier + FooterText Generated by CocoaPods - https://cocoapods.org diff --git a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-resources.sh b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-resources.sh index fe3f9c72..345301f2 100755 --- a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-resources.sh +++ b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo-resources.sh @@ -113,6 +113,6 @@ then if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" else - printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" fi fi diff --git a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.debug.xcconfig b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.debug.xcconfig index 958d2f0c..8d5a6cf2 100644 --- a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.debug.xcconfig +++ b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.debug.xcconfig @@ -1,8 +1,8 @@ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/YYCache" +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/YYCache" +OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"YYCache" -l"sqlite3" -framework "CoreFoundation" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.release.xcconfig b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.release.xcconfig index 958d2f0c..8d5a6cf2 100644 --- a/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.release.xcconfig +++ b/Demo/Pods/Target Support Files/Pods-XMNetworkingDemo/Pods-XMNetworkingDemo.release.xcconfig @@ -1,8 +1,8 @@ GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" -LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" -OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "Security" -framework "SystemConfiguration" +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/AFNetworking" "${PODS_ROOT}/Headers/Public/YYCache" +LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/YYCache" +OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/AFNetworking" -isystem "${PODS_ROOT}/Headers/Public/YYCache" +OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"YYCache" -l"sqlite3" -framework "CoreFoundation" -framework "CoreGraphics" -framework "MobileCoreServices" -framework "QuartzCore" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_PODFILE_DIR_PATH = ${SRCROOT}/. diff --git a/Demo/Pods/Target Support Files/YYCache/YYCache-dummy.m b/Demo/Pods/Target Support Files/YYCache/YYCache-dummy.m new file mode 100644 index 00000000..a17e4601 --- /dev/null +++ b/Demo/Pods/Target Support Files/YYCache/YYCache-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_YYCache : NSObject +@end +@implementation PodsDummy_YYCache +@end diff --git a/Demo/Pods/Target Support Files/YYCache/YYCache-prefix.pch b/Demo/Pods/Target Support Files/YYCache/YYCache-prefix.pch new file mode 100644 index 00000000..beb2a244 --- /dev/null +++ b/Demo/Pods/Target Support Files/YYCache/YYCache-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Demo/Pods/Target Support Files/YYCache/YYCache.xcconfig b/Demo/Pods/Target Support Files/YYCache/YYCache.xcconfig new file mode 100644 index 00000000..243e12c3 --- /dev/null +++ b/Demo/Pods/Target Support Files/YYCache/YYCache.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/YYCache +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/YYCache" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/YYCache" +OTHER_LDFLAGS = -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 +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES diff --git a/Demo/Pods/YYCache/LICENSE b/Demo/Pods/YYCache/LICENSE new file mode 100644 index 00000000..46be20bd --- /dev/null +++ b/Demo/Pods/YYCache/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 ibireme + +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. + diff --git a/Demo/Pods/YYCache/README.md b/Demo/Pods/YYCache/README.md new file mode 100755 index 00000000..46623b5c --- /dev/null +++ b/Demo/Pods/YYCache/README.md @@ -0,0 +1,171 @@ +YYCache +============== + +[![License MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/ibireme/YYCache/master/LICENSE)  +[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)  +[![CocoaPods](http://img.shields.io/cocoapods/v/YYCache.svg?style=flat)](http://cocoapods.org/?q= YYCache)  +[![CocoaPods](http://img.shields.io/cocoapods/p/YYCache.svg?style=flat)](http://cocoapods.org/?q= YYCache)  +[![Support](https://img.shields.io/badge/support-iOS%206%2B%20-blue.svg?style=flat)](https://www.apple.com/nl/ios/)  +[![Build Status](https://travis-ci.org/ibireme/YYCache.svg?branch=master)](https://travis-ci.org/ibireme/YYCache) + +High performance cache framework for iOS.
+(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 \. + + +### Carthage + +1. Add `github "ibireme/YYCache"` to your Cartfile. +2. Run `carthage update --platform ios` and add the framework to your project. +3. Import \. + + +### 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/).
+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. + + +

+--- +中文介绍 +============== +高性能 iOS 缓存框架。
+(该项目是 [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. 导入 \。 + + +### Carthage + +1. 在 Cartfile 中添加 `github "ibireme/YYCache"`。 +2. 执行 `carthage update --platform ios` 并将生成的 framework 添加到你的工程。 +3. 导入 \。 + + +### 手动安装 + +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/) + + diff --git a/Demo/Pods/YYCache/YYCache/YYCache.h b/Demo/Pods/YYCache/YYCache/YYCache.h new file mode 100644 index 00000000..f042ed77 --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYCache.h @@ -0,0 +1,206 @@ +// +// YYCache.h +// 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 + +#if __has_include() +FOUNDATION_EXPORT double YYCacheVersionNumber; +FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; +#import +#import +#import +#elif __has_include() +#import +#import +#import +#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)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 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)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)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 diff --git a/Demo/Pods/YYCache/YYCache/YYCache.m b/Demo/Pods/YYCache/YYCache/YYCache.m new file mode 100644 index 00000000..e6cdcba3 --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYCache.m @@ -0,0 +1,139 @@ +// +// YYCache.m +// 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)objectForKey:(NSString *)key { + id 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 object))block { + if (!block) return; + id 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 object) { + if (object && ![_memoryCache objectForKey:key]) { + [_memoryCache setObject:object forKey:key]; + } + block(key, object); + }]; + } +} + +- (void)setObject:(id)object forKey:(NSString *)key { + [_memoryCache setObject:object forKey:key]; + [_diskCache setObject:object forKey:key]; +} + +- (void)setObject:(id)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 diff --git a/Demo/Pods/YYCache/YYCache/YYDiskCache.h b/Demo/Pods/YYCache/YYCache/YYDiskCache.h new file mode 100644 index 00000000..dd193e43 --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYDiskCache.h @@ -0,0 +1,412 @@ +// +// YYDiskCache.h +// YYCache +// +// Created by ibireme on 15/2/11. +// 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 + +NS_ASSUME_NONNULL_BEGIN + +/** + YYDiskCache is a thread-safe cache that stores key-value pairs backed by SQLite + and file system (similar to NSURLCache's disk cache). + + YYDiskCache has these features: + + * It use LRU (least-recently-used) to remove objects. + * It can be controlled by cost, count, and age. + * It can be configured to automatically evict objects when there's no free disk space. + * It can automatically decide the storage type (sqlite/file) for each object to get + better performance. + + You may compile the latest version of sqlite and ignore the libsqlite3.dylib in + iOS system to get 2x~4x speed up. + */ +@interface YYDiskCache : NSObject + +#pragma mark - Attribute +///============================================================================= +/// @name Attribute +///============================================================================= + +/** The name of the cache. Default is nil. */ +@property (nullable, copy) NSString *name; + +/** The path of the cache (read-only). */ +@property (readonly) NSString *path; + +/** + If the object's data size (in bytes) is larger than this value, then object will + be stored as a file, otherwise the object will be stored in sqlite. + + 0 means all objects will be stored as separated files, NSUIntegerMax means all + objects will be stored in sqlite. + + The default value is 20480 (20KB). + */ +@property (readonly) NSUInteger inlineThreshold; + +/** + If this block is not nil, then the block will be used to archive object instead + of NSKeyedArchiver. You can use this block to support the objects which do not + conform to the `NSCoding` protocol. + + The default value is nil. + */ +@property (nullable, copy) NSData *(^customArchiveBlock)(id object); + +/** + If this block is not nil, then the block will be used to unarchive object instead + of NSKeyedUnarchiver. You can use this block to support the objects which do not + conform to the `NSCoding` protocol. + + The default value is nil. + */ +@property (nullable, copy) id (^customUnarchiveBlock)(NSData *data); + +/** + When an object needs to be saved as a file, this block will be invoked to generate + a file name for a specified key. If the block is nil, the cache use md5(key) as + default file name. + + The default value is nil. + */ +@property (nullable, copy) NSString *(^customFileNameBlock)(NSString *key); + + + +#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 background queue. + */ +@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 background queue. + */ +@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 objects could + be evicted later in background queue. + */ +@property NSTimeInterval ageLimit; + +/** + The minimum free disk space (in bytes) which the cache should kept. + + @discussion The default value is 0, which means no limit. + If the free disk space is lower than this value, the cache will remove objects + to free some disk space. This is not a strict limit—if the free disk space goes + over the limit, the objects could be evicted later in background queue. + */ +@property NSUInteger freeDiskSpaceLimit; + +/** + The auto trim check time interval in seconds. Default is 60 (1 minute). + + @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; + +/** + Set `YES` to enable error logs for debug. + */ +@property BOOL errorLogsEnabled; + +#pragma mark - Initializer +///============================================================================= +/// @name Initializer +///============================================================================= +- (instancetype)init UNAVAILABLE_ATTRIBUTE; ++ (instancetype)new UNAVAILABLE_ATTRIBUTE; + +/** + Create a new cache based on the specified path. + + @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. + + @return A new cache object, or nil if an error occurs. + + @warning If the cache instance for the specified path already exists in memory, + this method will return it directly, instead of creating a new instance. + */ +- (nullable instancetype)initWithPath:(NSString *)path; + +/** + The designated initializer. + + @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. + + @param threshold The data store inline threshold in bytes. If the object's data + size (in bytes) is larger than this value, then object will be stored as a + file, otherwise the object will be stored in sqlite. 0 means all objects will + be stored as separated files, NSUIntegerMax means all objects will be stored + in sqlite. If you don't know your object's size, 20480 is a good choice. + After first initialized you should not change this value of the specified path. + + @return A new cache object, or nil if an error occurs. + + @warning If the cache instance for the specified path already exists in memory, + this method will return it directly, instead of creating a new instance. + */ +- (nullable instancetype)initWithPath:(NSString *)path + inlineThreshold:(NSUInteger)threshold NS_DESIGNATED_INITIALIZER; + + +#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:(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)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:(void(^)(NSString *key, id _Nullable 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)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)object forKey:(NSString *)key withBlock:(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:(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; + + +/** + Returns the number of objects in this cache. + This method may blocks the calling thread until file read finished. + + @return The total objects count. + */ +- (NSInteger)totalCount; + +/** + Get the number of objects in this 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)totalCountWithBlock:(void(^)(NSInteger totalCount))block; + +/** + Returns the total cost (in bytes) of objects in this cache. + This method may blocks the calling thread until file read finished. + + @return The total objects cost in bytes. + */ +- (NSInteger)totalCost; + +/** + Get the total cost (in bytes) of objects in this 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)totalCostWithBlock:(void(^)(NSInteger totalCost))block; + + +#pragma mark - Trim +///============================================================================= +/// @name Trim +///============================================================================= + +/** + Removes objects from the cache use LRU, until the `totalCount` is below the specified value. + This method may blocks the calling thread until operation finished. + + @param count The total count allowed to remain after the cache has been trimmed. + */ +- (void)trimToCount:(NSUInteger)count; + +/** + Removes objects from the cache use LRU, until the `totalCount` is below the specified value. + This method returns immediately and invoke the passed block in background queue + when the operation finished. + + @param count The total count allowed to remain after the cache has been trimmed. + @param block A block which will be invoked in background queue when finished. + */ +- (void)trimToCount:(NSUInteger)count withBlock:(void(^)(void))block; + +/** + Removes objects from the cache use LRU, until the `totalCost` is below the specified value. + This method may blocks the calling thread until operation finished. + + @param cost The total cost allowed to remain after the cache has been trimmed. + */ +- (void)trimToCost:(NSUInteger)cost; + +/** + Removes objects from the cache use LRU, until the `totalCost` is below the specified value. + This method returns immediately and invoke the passed block in background queue + when the operation finished. + + @param cost The total cost allowed to remain after the cache has been trimmed. + @param block A block which will be invoked in background queue when finished. + */ +- (void)trimToCost:(NSUInteger)cost withBlock:(void(^)(void))block; + +/** + Removes objects from the cache use LRU, until all expiry objects removed by the specified value. + This method may blocks the calling thread until operation finished. + + @param age The maximum age of the object. + */ +- (void)trimToAge:(NSTimeInterval)age; + +/** + Removes objects from the cache use LRU, until all expiry objects removed by the specified value. + This method returns immediately and invoke the passed block in background queue + when the operation finished. + + @param age The maximum age of the object. + @param block A block which will be invoked in background queue when finished. + */ +- (void)trimToAge:(NSTimeInterval)age withBlock:(void(^)(void))block; + + +#pragma mark - Extended Data +///============================================================================= +/// @name Extended Data +///============================================================================= + +/** + Get extended data from an object. + + @discussion See 'setExtendedData:toObject:' for more information. + + @param object An object. + @return The extended data. + */ ++ (nullable NSData *)getExtendedDataFromObject:(id)object; + +/** + Set extended data to an object. + + @discussion You can set any extended data to an object before you save the object + to disk cache. The extended data will also be saved with this object. You can get + the extended data later with "getExtendedDataFromObject:". + + @param extendedData The extended data (pass nil to remove). + @param object The object. + */ ++ (void)setExtendedData:(nullable NSData *)extendedData toObject:(id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/Pods/YYCache/YYCache/YYDiskCache.m b/Demo/Pods/YYCache/YYCache/YYDiskCache.m new file mode 100644 index 00000000..735cc5df --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYDiskCache.m @@ -0,0 +1,458 @@ +// +// YYDiskCache.m +// YYCache +// +// Created by ibireme on 15/2/11. +// 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 "YYDiskCache.h" +#import "YYKVStorage.h" +#import +#import +#import +#import + +#define Lock() dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER) +#define Unlock() dispatch_semaphore_signal(self->_lock) + +static const int extended_data_key; + +/// Free disk space in bytes. +static int64_t _YYDiskSpaceFree() { + NSError *error = nil; + NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:&error]; + if (error) return -1; + int64_t space = [[attrs objectForKey:NSFileSystemFreeSize] longLongValue]; + if (space < 0) space = -1; + return space; +} + +/// String's md5 hash. +static NSString *_YYNSStringMD5(NSString *string) { + if (!string) return nil; + NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; + unsigned char result[CC_MD5_DIGEST_LENGTH]; + CC_MD5(data.bytes, (CC_LONG)data.length, result); + return [NSString stringWithFormat: + @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + result[0], result[1], result[2], result[3], + result[4], result[5], result[6], result[7], + result[8], result[9], result[10], result[11], + result[12], result[13], result[14], result[15] + ]; +} + +/// weak reference for all instances +static NSMapTable *_globalInstances; +static dispatch_semaphore_t _globalInstancesLock; + +static void _YYDiskCacheInitGlobal() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _globalInstancesLock = dispatch_semaphore_create(1); + _globalInstances = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0]; + }); +} + +static YYDiskCache *_YYDiskCacheGetGlobal(NSString *path) { + if (path.length == 0) return nil; + _YYDiskCacheInitGlobal(); + dispatch_semaphore_wait(_globalInstancesLock, DISPATCH_TIME_FOREVER); + id cache = [_globalInstances objectForKey:path]; + dispatch_semaphore_signal(_globalInstancesLock); + return cache; +} + +static void _YYDiskCacheSetGlobal(YYDiskCache *cache) { + if (cache.path.length == 0) return; + _YYDiskCacheInitGlobal(); + dispatch_semaphore_wait(_globalInstancesLock, DISPATCH_TIME_FOREVER); + [_globalInstances setObject:cache forKey:cache.path]; + dispatch_semaphore_signal(_globalInstancesLock); +} + + + +@implementation YYDiskCache { + YYKVStorage *_kv; + dispatch_semaphore_t _lock; + dispatch_queue_t _queue; +} + +- (void)_trimRecursively { + __weak typeof(self) _self = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + __strong typeof(_self) self = _self; + if (!self) return; + [self _trimInBackground]; + [self _trimRecursively]; + }); +} + +- (void)_trimInBackground { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + if (!self) return; + Lock(); + [self _trimToCost:self.costLimit]; + [self _trimToCount:self.countLimit]; + [self _trimToAge:self.ageLimit]; + [self _trimToFreeDiskSpace:self.freeDiskSpaceLimit]; + Unlock(); + }); +} + +- (void)_trimToCost:(NSUInteger)costLimit { + if (costLimit >= INT_MAX) return; + [_kv removeItemsToFitSize:(int)costLimit]; + +} + +- (void)_trimToCount:(NSUInteger)countLimit { + if (countLimit >= INT_MAX) return; + [_kv removeItemsToFitCount:(int)countLimit]; +} + +- (void)_trimToAge:(NSTimeInterval)ageLimit { + if (ageLimit <= 0) { + [_kv removeAllItems]; + return; + } + long timestamp = time(NULL); + if (timestamp <= ageLimit) return; + long age = timestamp - ageLimit; + if (age >= INT_MAX) return; + [_kv removeItemsEarlierThanTime:(int)age]; +} + +- (void)_trimToFreeDiskSpace:(NSUInteger)targetFreeDiskSpace { + if (targetFreeDiskSpace == 0) return; + int64_t totalBytes = [_kv getItemsSize]; + if (totalBytes <= 0) return; + int64_t diskFreeBytes = _YYDiskSpaceFree(); + if (diskFreeBytes < 0) return; + int64_t needTrimBytes = targetFreeDiskSpace - diskFreeBytes; + if (needTrimBytes <= 0) return; + int64_t costLimit = totalBytes - needTrimBytes; + if (costLimit < 0) costLimit = 0; + [self _trimToCost:(int)costLimit]; +} + +- (NSString *)_filenameForKey:(NSString *)key { + NSString *filename = nil; + if (_customFileNameBlock) filename = _customFileNameBlock(key); + if (!filename) filename = _YYNSStringMD5(key); + return filename; +} + +- (void)_appWillBeTerminated { + Lock(); + _kv = nil; + Unlock(); +} + +#pragma mark - public + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; +} + +- (instancetype)init { + @throw [NSException exceptionWithName:@"YYDiskCache init error" reason:@"YYDiskCache must be initialized with a path. Use 'initWithPath:' or 'initWithPath:inlineThreshold:' instead." userInfo:nil]; + return [self initWithPath:@"" inlineThreshold:0]; +} + +- (instancetype)initWithPath:(NSString *)path { + return [self initWithPath:path inlineThreshold:1024 * 20]; // 20KB +} + +- (instancetype)initWithPath:(NSString *)path + inlineThreshold:(NSUInteger)threshold { + self = [super init]; + if (!self) return nil; + + YYDiskCache *globalCache = _YYDiskCacheGetGlobal(path); + if (globalCache) return globalCache; + + YYKVStorageType type; + if (threshold == 0) { + type = YYKVStorageTypeFile; + } else if (threshold == NSUIntegerMax) { + type = YYKVStorageTypeSQLite; + } else { + type = YYKVStorageTypeMixed; + } + + YYKVStorage *kv = [[YYKVStorage alloc] initWithPath:path type:type]; + if (!kv) return nil; + + _kv = kv; + _path = path; + _lock = dispatch_semaphore_create(1); + _queue = dispatch_queue_create("com.ibireme.cache.disk", DISPATCH_QUEUE_CONCURRENT); + _inlineThreshold = threshold; + _countLimit = NSUIntegerMax; + _costLimit = NSUIntegerMax; + _ageLimit = DBL_MAX; + _freeDiskSpaceLimit = 0; + _autoTrimInterval = 60; + + [self _trimRecursively]; + _YYDiskCacheSetGlobal(self); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appWillBeTerminated) name:UIApplicationWillTerminateNotification object:nil]; + return self; +} + +- (BOOL)containsObjectForKey:(NSString *)key { + if (!key) return NO; + Lock(); + BOOL contains = [_kv itemExistsForKey:key]; + Unlock(); + return contains; +} + +- (void)containsObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key, BOOL contains))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + BOOL contains = [self containsObjectForKey:key]; + block(key, contains); + }); +} + +- (id)objectForKey:(NSString *)key { + if (!key) return nil; + Lock(); + YYKVStorageItem *item = [_kv getItemForKey:key]; + Unlock(); + if (!item.value) return nil; + + id object = nil; + if (_customUnarchiveBlock) { + object = _customUnarchiveBlock(item.value); + } else { + @try { + object = [NSKeyedUnarchiver unarchiveObjectWithData:item.value]; + } + @catch (NSException *exception) { + // nothing to do... + } + } + if (object && item.extendedData) { + [YYDiskCache setExtendedData:item.extendedData toObject:object]; + } + return object; +} + +- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id object))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + id object = [self objectForKey:key]; + block(key, object); + }); +} + +- (void)setObject:(id)object forKey:(NSString *)key { + if (!key) return; + if (!object) { + [self removeObjectForKey:key]; + return; + } + + NSData *extendedData = [YYDiskCache getExtendedDataFromObject:object]; + NSData *value = nil; + if (_customArchiveBlock) { + value = _customArchiveBlock(object); + } else { + @try { + value = [NSKeyedArchiver archivedDataWithRootObject:object]; + } + @catch (NSException *exception) { + // nothing to do... + } + } + if (!value) return; + NSString *filename = nil; + if (_kv.type != YYKVStorageTypeSQLite) { + if (value.length > _inlineThreshold) { + filename = [self _filenameForKey:key]; + } + } + + Lock(); + [_kv saveItemWithKey:key value:value filename:filename extendedData:extendedData]; + Unlock(); +} + +- (void)setObject:(id)object forKey:(NSString *)key withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self setObject:object forKey:key]; + if (block) block(); + }); +} + +- (void)removeObjectForKey:(NSString *)key { + if (!key) return; + Lock(); + [_kv removeItemForKey:key]; + Unlock(); +} + +- (void)removeObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self removeObjectForKey:key]; + if (block) block(key); + }); +} + +- (void)removeAllObjects { + Lock(); + [_kv removeAllItems]; + Unlock(); +} + +- (void)removeAllObjectsWithBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self removeAllObjects]; + if (block) block(); + }); +} + +- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress + endBlock:(void(^)(BOOL error))end { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + if (!self) { + if (end) end(YES); + return; + } + Lock(); + [_kv removeAllItemsWithProgressBlock:progress endBlock:end]; + Unlock(); + }); +} + +- (NSInteger)totalCount { + Lock(); + int count = [_kv getItemsCount]; + Unlock(); + return count; +} + +- (void)totalCountWithBlock:(void(^)(NSInteger totalCount))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + NSInteger totalCount = [self totalCount]; + block(totalCount); + }); +} + +- (NSInteger)totalCost { + Lock(); + int count = [_kv getItemsSize]; + Unlock(); + return count; +} + +- (void)totalCostWithBlock:(void(^)(NSInteger totalCost))block { + if (!block) return; + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + NSInteger totalCost = [self totalCost]; + block(totalCost); + }); +} + +- (void)trimToCount:(NSUInteger)count { + Lock(); + [self _trimToCount:count]; + Unlock(); +} + +- (void)trimToCount:(NSUInteger)count withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self trimToCount:count]; + if (block) block(); + }); +} + +- (void)trimToCost:(NSUInteger)cost { + Lock(); + [self _trimToCost:cost]; + Unlock(); +} + +- (void)trimToCost:(NSUInteger)cost withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self trimToCost:cost]; + if (block) block(); + }); +} + +- (void)trimToAge:(NSTimeInterval)age { + Lock(); + [self _trimToAge:age]; + Unlock(); +} + +- (void)trimToAge:(NSTimeInterval)age withBlock:(void(^)(void))block { + __weak typeof(self) _self = self; + dispatch_async(_queue, ^{ + __strong typeof(_self) self = _self; + [self trimToAge:age]; + if (block) block(); + }); +} + ++ (NSData *)getExtendedDataFromObject:(id)object { + if (!object) return nil; + return (NSData *)objc_getAssociatedObject(object, &extended_data_key); +} + ++ (void)setExtendedData:(NSData *)extendedData toObject:(id)object { + if (!object) return; + objc_setAssociatedObject(object, &extended_data_key, extendedData, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSString *)description { + if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@:%@)", self.class, self, _name, _path]; + else return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _path]; +} + +- (BOOL)errorLogsEnabled { + Lock(); + BOOL enabled = _kv.errorLogsEnabled; + Unlock(); + return enabled; +} + +- (void)setErrorLogsEnabled:(BOOL)errorLogsEnabled { + Lock(); + _kv.errorLogsEnabled = errorLogsEnabled; + Unlock(); +} + +@end diff --git a/Demo/Pods/YYCache/YYCache/YYKVStorage.h b/Demo/Pods/YYCache/YYCache/YYKVStorage.h new file mode 100644 index 00000000..939a6e4c --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYKVStorage.h @@ -0,0 +1,325 @@ +// +// YYKVStorage.h +// YYCache +// +// Created by ibireme on 15/4/22. +// 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 + +NS_ASSUME_NONNULL_BEGIN + +/** + YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data. + Typically, you should not use this class directly. + */ +@interface YYKVStorageItem : NSObject +@property (nonatomic, strong) NSString *key; ///< key +@property (nonatomic, strong) NSData *value; ///< value +@property (nullable, nonatomic, strong) NSString *filename; ///< filename (nil if inline) +@property (nonatomic) int size; ///< value's size in bytes +@property (nonatomic) int modTime; ///< modification unix timestamp +@property (nonatomic) int accessTime; ///< last access unix timestamp +@property (nullable, nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data) +@end + +/** + Storage type, indicated where the `YYKVStorageItem.value` stored. + + @discussion Typically, write data to sqlite is faster than extern file, but + reading performance is dependent on data size. In my test (on iPhone 6 64G), + read data from extern file is faster than from sqlite when the data is larger + than 20KB. + + * If you want to store large number of small datas (such as contacts cache), + use YYKVStorageTypeSQLite to get better performance. + * If you want to store large files (such as image cache), + use YYKVStorageTypeFile to get better performance. + * You can use YYKVStorageTypeMixed and choice your storage type for each item. + + See for more information. + */ +typedef NS_ENUM(NSUInteger, YYKVStorageType) { + + /// The `value` is stored as a file in file system. + YYKVStorageTypeFile = 0, + + /// The `value` is stored in sqlite with blob type. + YYKVStorageTypeSQLite = 1, + + /// The `value` is stored in file system or sqlite based on your choice. + YYKVStorageTypeMixed = 2, +}; + + + +/** + YYKVStorage is a key-value storage based on sqlite and file system. + Typically, you should not use this class directly. + + @discussion The designated initializer for YYKVStorage is `initWithPath:type:`. + After initialized, a directory is created based on the `path` to hold key-value data. + Once initialized you should not read or write this directory without the instance. + + You may compile the latest version of sqlite and ignore the libsqlite3.dylib in + iOS system to get 2x~4x speed up. + + @warning The instance of this class is *NOT* thread safe, you need to make sure + that there's only one thread to access the instance at the same time. If you really + need to process large amounts of data in multi-thread, you should split the data + to multiple KVStorage instance (sharding). + */ +@interface YYKVStorage : NSObject + +#pragma mark - Attribute +///============================================================================= +/// @name Attribute +///============================================================================= + +@property (nonatomic, readonly) NSString *path; ///< The path of this storage. +@property (nonatomic, readonly) YYKVStorageType type; ///< The type of this storage. +@property (nonatomic) BOOL errorLogsEnabled; ///< Set `YES` to enable error logs for debug. + +#pragma mark - Initializer +///============================================================================= +/// @name Initializer +///============================================================================= +- (instancetype)init UNAVAILABLE_ATTRIBUTE; ++ (instancetype)new UNAVAILABLE_ATTRIBUTE; + +/** + The designated initializer. + + @param path Full path of a directory in which the storage will write data. If + the directory is not exists, it will try to create one, otherwise it will + read the data in this directory. + @param type The storage type. After first initialized you should not change the + type of the specified path. + @return A new storage object, or nil if an error occurs. + @warning Multiple instances with the same path will make the storage unstable. + */ +- (nullable instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type NS_DESIGNATED_INITIALIZER; + + +#pragma mark - Save Items +///============================================================================= +/// @name Save Items +///============================================================================= + +/** + Save an item or update the item with 'key' if it already exists. + + @discussion This method will save the item.key, item.value, item.filename and + item.extendedData to disk or sqlite, other properties will be ignored. item.key + and item.value should not be empty (nil or zero length). + + If the `type` is YYKVStorageTypeFile, then the item.filename should not be empty. + If the `type` is YYKVStorageTypeSQLite, then the item.filename will be ignored. + It the `type` is YYKVStorageTypeMixed, then the item.value will be saved to file + system if the item.filename is not empty, otherwise it will be saved to sqlite. + + @param item An item. + @return Whether succeed. + */ +- (BOOL)saveItem:(YYKVStorageItem *)item; + +/** + Save an item or update the item with 'key' if it already exists. + + @discussion This method will save the key-value pair to sqlite. If the `type` is + YYKVStorageTypeFile, then this method will failed. + + @param key The key, should not be empty (nil or zero length). + @param value The key, should not be empty (nil or zero length). + @return Whether succeed. + */ +- (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value; + +/** + Save an item or update the item with 'key' if it already exists. + + @discussion + If the `type` is YYKVStorageTypeFile, then the `filename` should not be empty. + If the `type` is YYKVStorageTypeSQLite, then the `filename` will be ignored. + It the `type` is YYKVStorageTypeMixed, then the `value` will be saved to file + system if the `filename` is not empty, otherwise it will be saved to sqlite. + + @param key The key, should not be empty (nil or zero length). + @param value The key, should not be empty (nil or zero length). + @param filename The filename. + @param extendedData The extended data for this item (pass nil to ignore it). + + @return Whether succeed. + */ +- (BOOL)saveItemWithKey:(NSString *)key + value:(NSData *)value + filename:(nullable NSString *)filename + extendedData:(nullable NSData *)extendedData; + +#pragma mark - Remove Items +///============================================================================= +/// @name Remove Items +///============================================================================= + +/** + Remove an item with 'key'. + + @param key The item's key. + @return Whether succeed. + */ +- (BOOL)removeItemForKey:(NSString *)key; + +/** + Remove items with an array of keys. + + @param keys An array of specified keys. + + @return Whether succeed. + */ +- (BOOL)removeItemForKeys:(NSArray *)keys; + +/** + Remove all items which `value` is larger than a specified size. + + @param size The maximum size in bytes. + @return Whether succeed. + */ +- (BOOL)removeItemsLargerThanSize:(int)size; + +/** + Remove all items which last access time is earlier than a specified timestamp. + + @param time The specified unix timestamp. + @return Whether succeed. + */ +- (BOOL)removeItemsEarlierThanTime:(int)time; + +/** + Remove items to make the total size not larger than a specified size. + The least recently used (LRU) items will be removed first. + + @param maxSize The specified size in bytes. + @return Whether succeed. + */ +- (BOOL)removeItemsToFitSize:(int)maxSize; + +/** + Remove items to make the total count not larger than a specified count. + The least recently used (LRU) items will be removed first. + + @param maxCount The specified item count. + @return Whether succeed. + */ +- (BOOL)removeItemsToFitCount:(int)maxCount; + +/** + Remove all items in background queue. + + @discussion This method will remove the files and sqlite database to a trash + folder, and then clear the folder in background queue. So this method is much + faster than `removeAllItemsWithProgressBlock:endBlock:`. + + @return Whether succeed. + */ +- (BOOL)removeAllItems; + +/** + Remove all items. + + @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)removeAllItemsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress + endBlock:(nullable void(^)(BOOL error))end; + + +#pragma mark - Get Items +///============================================================================= +/// @name Get Items +///============================================================================= + +/** + Get item with a specified key. + + @param key A specified key. + @return Item for the key, or nil if not exists / error occurs. + */ +- (nullable YYKVStorageItem *)getItemForKey:(NSString *)key; + +/** + Get item information with a specified key. + The `value` in this item will be ignored. + + @param key A specified key. + @return Item information for the key, or nil if not exists / error occurs. + */ +- (nullable YYKVStorageItem *)getItemInfoForKey:(NSString *)key; + +/** + Get item value with a specified key. + + @param key A specified key. + @return Item's value, or nil if not exists / error occurs. + */ +- (nullable NSData *)getItemValueForKey:(NSString *)key; + +/** + Get items with an array of keys. + + @param keys An array of specified keys. + @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. + */ +- (nullable NSArray *)getItemForKeys:(NSArray *)keys; + +/** + Get item infomartions with an array of keys. + The `value` in items will be ignored. + + @param keys An array of specified keys. + @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. + */ +- (nullable NSArray *)getItemInfoForKeys:(NSArray *)keys; + +/** + Get items value with an array of keys. + + @param keys An array of specified keys. + @return A dictionary which key is 'key' and value is 'value', or nil if not + exists / error occurs. + */ +- (nullable NSDictionary *)getItemValueForKeys:(NSArray *)keys; + +#pragma mark - Get Storage Status +///============================================================================= +/// @name Get Storage Status +///============================================================================= + +/** + Whether an item exists for a specified key. + + @param key A specified key. + + @return `YES` if there's an item exists for the key, `NO` if not exists or an error occurs. + */ +- (BOOL)itemExistsForKey:(NSString *)key; + +/** + Get total item count. + @return Total item count, -1 when an error occurs. + */ +- (int)getItemsCount; + +/** + Get item value's total size in bytes. + @return Total size in bytes, -1 when an error occurs. + */ +- (int)getItemsSize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/Pods/YYCache/YYCache/YYKVStorage.m b/Demo/Pods/YYCache/YYCache/YYKVStorage.m new file mode 100644 index 00000000..501dfdde --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYKVStorage.m @@ -0,0 +1,1069 @@ +// +// YYKVStorage.m +// YYCache +// +// Created by ibireme on 15/4/22. +// 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 "YYKVStorage.h" +#import +#import + +#if __has_include() +#import +#else +#import "sqlite3.h" +#endif + + +static const NSUInteger kMaxErrorRetryCount = 8; +static const NSTimeInterval kMinRetryTimeInterval = 2.0; +static const int kPathLengthMax = PATH_MAX - 64; +static NSString *const kDBFileName = @"manifest.sqlite"; +static NSString *const kDBShmFileName = @"manifest.sqlite-shm"; +static NSString *const kDBWalFileName = @"manifest.sqlite-wal"; +static NSString *const kDataDirectoryName = @"data"; +static NSString *const kTrashDirectoryName = @"trash"; + + +/* + File: + /path/ + /manifest.sqlite + /manifest.sqlite-shm + /manifest.sqlite-wal + /data/ + /e10adc3949ba59abbe56e057f20f883e + /e10adc3949ba59abbe56e057f20f883e + /trash/ + /unused_file_or_folder + + SQL: + create table if not exists manifest ( + key text, + filename text, + size integer, + inline_data blob, + modification_time integer, + last_access_time integer, + extended_data blob, + primary key(key) + ); + create index if not exists last_access_time_idx on manifest(last_access_time); + */ + +/// Returns nil in App Extension. +static UIApplication *_YYSharedApplication() { + static BOOL isAppExtension = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class cls = NSClassFromString(@"UIApplication"); + if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES; + if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES; + }); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)]; +#pragma clang diagnostic pop +} + + +@implementation YYKVStorageItem +@end + +@implementation YYKVStorage { + dispatch_queue_t _trashQueue; + + NSString *_path; + NSString *_dbPath; + NSString *_dataPath; + NSString *_trashPath; + + sqlite3 *_db; + CFMutableDictionaryRef _dbStmtCache; + NSTimeInterval _dbLastOpenErrorTime; + NSUInteger _dbOpenErrorCount; +} + + +#pragma mark - db + +- (BOOL)_dbOpen { + if (_db) return YES; + + int result = sqlite3_open(_dbPath.UTF8String, &_db); + if (result == SQLITE_OK) { + CFDictionaryKeyCallBacks keyCallbacks = kCFCopyStringDictionaryKeyCallBacks; + CFDictionaryValueCallBacks valueCallbacks = {0}; + _dbStmtCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &keyCallbacks, &valueCallbacks); + _dbLastOpenErrorTime = 0; + _dbOpenErrorCount = 0; + return YES; + } else { + _db = NULL; + if (_dbStmtCache) CFRelease(_dbStmtCache); + _dbStmtCache = NULL; + _dbLastOpenErrorTime = CACurrentMediaTime(); + _dbOpenErrorCount++; + + if (_errorLogsEnabled) { + NSLog(@"%s line:%d sqlite open failed (%d).", __FUNCTION__, __LINE__, result); + } + return NO; + } +} + +- (BOOL)_dbClose { + if (!_db) return YES; + + int result = 0; + BOOL retry = NO; + BOOL stmtFinalized = NO; + + if (_dbStmtCache) CFRelease(_dbStmtCache); + _dbStmtCache = NULL; + + do { + retry = NO; + result = sqlite3_close(_db); + if (result == SQLITE_BUSY || result == SQLITE_LOCKED) { + if (!stmtFinalized) { + stmtFinalized = YES; + sqlite3_stmt *stmt; + while ((stmt = sqlite3_next_stmt(_db, nil)) != 0) { + sqlite3_finalize(stmt); + retry = YES; + } + } + } else if (result != SQLITE_OK) { + if (_errorLogsEnabled) { + NSLog(@"%s line:%d sqlite close failed (%d).", __FUNCTION__, __LINE__, result); + } + } + } while (retry); + _db = NULL; + return YES; +} + +- (BOOL)_dbCheck { + if (!_db) { + if (_dbOpenErrorCount < kMaxErrorRetryCount && + CACurrentMediaTime() - _dbLastOpenErrorTime > kMinRetryTimeInterval) { + return [self _dbOpen] && [self _dbInitialize]; + } else { + return NO; + } + } + return YES; +} + +- (BOOL)_dbInitialize { + NSString *sql = @"pragma journal_mode = wal; pragma synchronous = normal; create table if not exists manifest (key text, filename text, size integer, inline_data blob, modification_time integer, last_access_time integer, extended_data blob, primary key(key)); create index if not exists last_access_time_idx on manifest(last_access_time);"; + return [self _dbExecute:sql]; +} + +- (void)_dbCheckpoint { + if (![self _dbCheck]) return; + // Cause a checkpoint to occur, merge `sqlite-wal` file to `sqlite` file. + sqlite3_wal_checkpoint(_db, NULL); +} + +- (BOOL)_dbExecute:(NSString *)sql { + if (sql.length == 0) return NO; + if (![self _dbCheck]) return NO; + + char *error = NULL; + int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &error); + if (error) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite exec error (%d): %s", __FUNCTION__, __LINE__, result, error); + sqlite3_free(error); + } + + return result == SQLITE_OK; +} + +- (sqlite3_stmt *)_dbPrepareStmt:(NSString *)sql { + if (![self _dbCheck] || sql.length == 0 || !_dbStmtCache) return NULL; + sqlite3_stmt *stmt = (sqlite3_stmt *)CFDictionaryGetValue(_dbStmtCache, (__bridge const void *)(sql)); + if (!stmt) { + int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); + if (result != SQLITE_OK) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite stmt prepare error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NULL; + } + CFDictionarySetValue(_dbStmtCache, (__bridge const void *)(sql), stmt); + } else { + sqlite3_reset(stmt); + } + return stmt; +} + +- (NSString *)_dbJoinedKeys:(NSArray *)keys { + NSMutableString *string = [NSMutableString new]; + for (NSUInteger i = 0,max = keys.count; i < max; i++) { + [string appendString:@"?"]; + if (i + 1 != max) { + [string appendString:@","]; + } + } + return string; +} + +- (void)_dbBindJoinedKeys:(NSArray *)keys stmt:(sqlite3_stmt *)stmt fromIndex:(int)index{ + for (int i = 0, max = (int)keys.count; i < max; i++) { + NSString *key = keys[i]; + sqlite3_bind_text(stmt, index + i, key.UTF8String, -1, NULL); + } +} + +- (BOOL)_dbSaveWithKey:(NSString *)key value:(NSData *)value fileName:(NSString *)fileName extendedData:(NSData *)extendedData { + NSString *sql = @"insert or replace into manifest (key, filename, size, inline_data, modification_time, last_access_time, extended_data) values (?1, ?2, ?3, ?4, ?5, ?6, ?7);"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return NO; + + int timestamp = (int)time(NULL); + sqlite3_bind_text(stmt, 1, key.UTF8String, -1, NULL); + sqlite3_bind_text(stmt, 2, fileName.UTF8String, -1, NULL); + sqlite3_bind_int(stmt, 3, (int)value.length); + if (fileName.length == 0) { + sqlite3_bind_blob(stmt, 4, value.bytes, (int)value.length, 0); + } else { + sqlite3_bind_blob(stmt, 4, NULL, 0, 0); + } + sqlite3_bind_int(stmt, 5, timestamp); + sqlite3_bind_int(stmt, 6, timestamp); + sqlite3_bind_blob(stmt, 7, extendedData.bytes, (int)extendedData.length, 0); + + int result = sqlite3_step(stmt); + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite insert error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (BOOL)_dbUpdateAccessTimeWithKey:(NSString *)key { + NSString *sql = @"update manifest set last_access_time = ?1 where key = ?2;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return NO; + sqlite3_bind_int(stmt, 1, (int)time(NULL)); + sqlite3_bind_text(stmt, 2, key.UTF8String, -1, NULL); + int result = sqlite3_step(stmt); + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite update error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (BOOL)_dbUpdateAccessTimeWithKeys:(NSArray *)keys { + if (![self _dbCheck]) return NO; + int t = (int)time(NULL); + NSString *sql = [NSString stringWithFormat:@"update manifest set last_access_time = %d where key in (%@);", t, [self _dbJoinedKeys:keys]]; + + sqlite3_stmt *stmt = NULL; + int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); + if (result != SQLITE_OK) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite stmt prepare error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; + result = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite update error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (BOOL)_dbDeleteItemWithKey:(NSString *)key { + NSString *sql = @"delete from manifest where key = ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return NO; + sqlite3_bind_text(stmt, 1, key.UTF8String, -1, NULL); + + int result = sqlite3_step(stmt); + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d db delete error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (BOOL)_dbDeleteItemWithKeys:(NSArray *)keys { + if (![self _dbCheck]) return NO; + NSString *sql = [NSString stringWithFormat:@"delete from manifest where key in (%@);", [self _dbJoinedKeys:keys]]; + sqlite3_stmt *stmt = NULL; + int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); + if (result != SQLITE_OK) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite stmt prepare error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; + result = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if (result == SQLITE_ERROR) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite delete error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (BOOL)_dbDeleteItemsWithSizeLargerThan:(int)size { + NSString *sql = @"delete from manifest where size > ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return NO; + sqlite3_bind_int(stmt, 1, size); + int result = sqlite3_step(stmt); + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite delete error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (BOOL)_dbDeleteItemsWithTimeEarlierThan:(int)time { + NSString *sql = @"delete from manifest where last_access_time < ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return NO; + sqlite3_bind_int(stmt, 1, time); + int result = sqlite3_step(stmt); + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite delete error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return NO; + } + return YES; +} + +- (YYKVStorageItem *)_dbGetItemFromStmt:(sqlite3_stmt *)stmt excludeInlineData:(BOOL)excludeInlineData { + int i = 0; + char *key = (char *)sqlite3_column_text(stmt, i++); + char *filename = (char *)sqlite3_column_text(stmt, i++); + int size = sqlite3_column_int(stmt, i++); + const void *inline_data = excludeInlineData ? NULL : sqlite3_column_blob(stmt, i); + int inline_data_bytes = excludeInlineData ? 0 : sqlite3_column_bytes(stmt, i++); + int modification_time = sqlite3_column_int(stmt, i++); + int last_access_time = sqlite3_column_int(stmt, i++); + const void *extended_data = sqlite3_column_blob(stmt, i); + int extended_data_bytes = sqlite3_column_bytes(stmt, i++); + + YYKVStorageItem *item = [YYKVStorageItem new]; + if (key) item.key = [NSString stringWithUTF8String:key]; + if (filename && *filename != 0) item.filename = [NSString stringWithUTF8String:filename]; + item.size = size; + if (inline_data_bytes > 0 && inline_data) item.value = [NSData dataWithBytes:inline_data length:inline_data_bytes]; + item.modTime = modification_time; + item.accessTime = last_access_time; + if (extended_data_bytes > 0 && extended_data) item.extendedData = [NSData dataWithBytes:extended_data length:extended_data_bytes]; + return item; +} + +- (YYKVStorageItem *)_dbGetItemWithKey:(NSString *)key excludeInlineData:(BOOL)excludeInlineData { + NSString *sql = excludeInlineData ? @"select key, filename, size, modification_time, last_access_time, extended_data from manifest where key = ?1;" : @"select key, filename, size, inline_data, modification_time, last_access_time, extended_data from manifest where key = ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return nil; + sqlite3_bind_text(stmt, 1, key.UTF8String, -1, NULL); + + YYKVStorageItem *item = nil; + int result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + item = [self _dbGetItemFromStmt:stmt excludeInlineData:excludeInlineData]; + } else { + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + } + } + return item; +} + +- (NSMutableArray *)_dbGetItemWithKeys:(NSArray *)keys excludeInlineData:(BOOL)excludeInlineData { + if (![self _dbCheck]) return nil; + NSString *sql; + if (excludeInlineData) { + sql = [NSString stringWithFormat:@"select key, filename, size, modification_time, last_access_time, extended_data from manifest where key in (%@);", [self _dbJoinedKeys:keys]]; + } else { + sql = [NSString stringWithFormat:@"select key, filename, size, inline_data, modification_time, last_access_time, extended_data from manifest where key in (%@)", [self _dbJoinedKeys:keys]]; + } + + sqlite3_stmt *stmt = NULL; + int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); + if (result != SQLITE_OK) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite stmt prepare error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return nil; + } + + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; + NSMutableArray *items = [NSMutableArray new]; + do { + result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + YYKVStorageItem *item = [self _dbGetItemFromStmt:stmt excludeInlineData:excludeInlineData]; + if (item) [items addObject:item]; + } else if (result == SQLITE_DONE) { + break; + } else { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + items = nil; + break; + } + } while (1); + sqlite3_finalize(stmt); + return items; +} + +- (NSData *)_dbGetValueWithKey:(NSString *)key { + NSString *sql = @"select inline_data from manifest where key = ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return nil; + sqlite3_bind_text(stmt, 1, key.UTF8String, -1, NULL); + + int result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + const void *inline_data = sqlite3_column_blob(stmt, 0); + int inline_data_bytes = sqlite3_column_bytes(stmt, 0); + if (!inline_data || inline_data_bytes <= 0) return nil; + return [NSData dataWithBytes:inline_data length:inline_data_bytes]; + } else { + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + } + return nil; + } +} + +- (NSString *)_dbGetFilenameWithKey:(NSString *)key { + NSString *sql = @"select filename from manifest where key = ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return nil; + sqlite3_bind_text(stmt, 1, key.UTF8String, -1, NULL); + int result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + char *filename = (char *)sqlite3_column_text(stmt, 0); + if (filename && *filename != 0) { + return [NSString stringWithUTF8String:filename]; + } + } else { + if (result != SQLITE_DONE) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + } + } + return nil; +} + +- (NSMutableArray *)_dbGetFilenameWithKeys:(NSArray *)keys { + if (![self _dbCheck]) return nil; + NSString *sql = [NSString stringWithFormat:@"select filename from manifest where key in (%@);", [self _dbJoinedKeys:keys]]; + sqlite3_stmt *stmt = NULL; + int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); + if (result != SQLITE_OK) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite stmt prepare error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return nil; + } + + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; + NSMutableArray *filenames = [NSMutableArray new]; + do { + result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + char *filename = (char *)sqlite3_column_text(stmt, 0); + if (filename && *filename != 0) { + NSString *name = [NSString stringWithUTF8String:filename]; + if (name) [filenames addObject:name]; + } + } else if (result == SQLITE_DONE) { + break; + } else { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + filenames = nil; + break; + } + } while (1); + sqlite3_finalize(stmt); + return filenames; +} + +- (NSMutableArray *)_dbGetFilenamesWithSizeLargerThan:(int)size { + NSString *sql = @"select filename from manifest where size > ?1 and filename is not null;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return nil; + sqlite3_bind_int(stmt, 1, size); + + NSMutableArray *filenames = [NSMutableArray new]; + do { + int result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + char *filename = (char *)sqlite3_column_text(stmt, 0); + if (filename && *filename != 0) { + NSString *name = [NSString stringWithUTF8String:filename]; + if (name) [filenames addObject:name]; + } + } else if (result == SQLITE_DONE) { + break; + } else { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + filenames = nil; + break; + } + } while (1); + return filenames; +} + +- (NSMutableArray *)_dbGetFilenamesWithTimeEarlierThan:(int)time { + NSString *sql = @"select filename from manifest where last_access_time < ?1 and filename is not null;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return nil; + sqlite3_bind_int(stmt, 1, time); + + NSMutableArray *filenames = [NSMutableArray new]; + do { + int result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + char *filename = (char *)sqlite3_column_text(stmt, 0); + if (filename && *filename != 0) { + NSString *name = [NSString stringWithUTF8String:filename]; + if (name) [filenames addObject:name]; + } + } else if (result == SQLITE_DONE) { + break; + } else { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + filenames = nil; + break; + } + } while (1); + return filenames; +} + +- (NSMutableArray *)_dbGetItemSizeInfoOrderByTimeAscWithLimit:(int)count { + NSString *sql = @"select key, filename, size from manifest order by last_access_time asc limit ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return nil; + sqlite3_bind_int(stmt, 1, count); + + NSMutableArray *items = [NSMutableArray new]; + do { + int result = sqlite3_step(stmt); + if (result == SQLITE_ROW) { + char *key = (char *)sqlite3_column_text(stmt, 0); + char *filename = (char *)sqlite3_column_text(stmt, 1); + int size = sqlite3_column_int(stmt, 2); + NSString *keyStr = key ? [NSString stringWithUTF8String:key] : nil; + if (keyStr) { + YYKVStorageItem *item = [YYKVStorageItem new]; + item.key = key ? [NSString stringWithUTF8String:key] : nil; + item.filename = filename ? [NSString stringWithUTF8String:filename] : nil; + item.size = size; + [items addObject:item]; + } + } else if (result == SQLITE_DONE) { + break; + } else { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + items = nil; + break; + } + } while (1); + return items; +} + +- (int)_dbGetItemCountWithKey:(NSString *)key { + NSString *sql = @"select count(key) from manifest where key = ?1;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return -1; + sqlite3_bind_text(stmt, 1, key.UTF8String, -1, NULL); + int result = sqlite3_step(stmt); + if (result != SQLITE_ROW) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return -1; + } + return sqlite3_column_int(stmt, 0); +} + +- (int)_dbGetTotalItemSize { + NSString *sql = @"select sum(size) from manifest;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return -1; + int result = sqlite3_step(stmt); + if (result != SQLITE_ROW) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return -1; + } + return sqlite3_column_int(stmt, 0); +} + +- (int)_dbGetTotalItemCount { + NSString *sql = @"select count(*) from manifest;"; + sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; + if (!stmt) return -1; + int result = sqlite3_step(stmt); + if (result != SQLITE_ROW) { + if (_errorLogsEnabled) NSLog(@"%s line:%d sqlite query error (%d): %s", __FUNCTION__, __LINE__, result, sqlite3_errmsg(_db)); + return -1; + } + return sqlite3_column_int(stmt, 0); +} + + +#pragma mark - file + +- (BOOL)_fileWriteWithName:(NSString *)filename data:(NSData *)data { + NSString *path = [_dataPath stringByAppendingPathComponent:filename]; + return [data writeToFile:path atomically:NO]; +} + +- (NSData *)_fileReadWithName:(NSString *)filename { + NSString *path = [_dataPath stringByAppendingPathComponent:filename]; + NSData *data = [NSData dataWithContentsOfFile:path]; + return data; +} + +- (BOOL)_fileDeleteWithName:(NSString *)filename { + NSString *path = [_dataPath stringByAppendingPathComponent:filename]; + return [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; +} + +- (BOOL)_fileMoveAllToTrash { + CFUUIDRef uuidRef = CFUUIDCreate(NULL); + CFStringRef uuid = CFUUIDCreateString(NULL, uuidRef); + CFRelease(uuidRef); + NSString *tmpPath = [_trashPath stringByAppendingPathComponent:(__bridge NSString *)(uuid)]; + BOOL suc = [[NSFileManager defaultManager] moveItemAtPath:_dataPath toPath:tmpPath error:nil]; + if (suc) { + suc = [[NSFileManager defaultManager] createDirectoryAtPath:_dataPath withIntermediateDirectories:YES attributes:nil error:NULL]; + } + CFRelease(uuid); + return suc; +} + +- (void)_fileEmptyTrashInBackground { + NSString *trashPath = _trashPath; + dispatch_queue_t queue = _trashQueue; + dispatch_async(queue, ^{ + NSFileManager *manager = [NSFileManager new]; + NSArray *directoryContents = [manager contentsOfDirectoryAtPath:trashPath error:NULL]; + for (NSString *path in directoryContents) { + NSString *fullPath = [trashPath stringByAppendingPathComponent:path]; + [manager removeItemAtPath:fullPath error:NULL]; + } + }); +} + + +#pragma mark - private + +/** + Delete all files and empty in background. + Make sure the db is closed. + */ +- (void)_reset { + [[NSFileManager defaultManager] removeItemAtPath:[_path stringByAppendingPathComponent:kDBFileName] error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:[_path stringByAppendingPathComponent:kDBShmFileName] error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:[_path stringByAppendingPathComponent:kDBWalFileName] error:nil]; + [self _fileMoveAllToTrash]; + [self _fileEmptyTrashInBackground]; +} + +#pragma mark - public + +- (instancetype)init { + @throw [NSException exceptionWithName:@"YYKVStorage init error" reason:@"Please use the designated initializer and pass the 'path' and 'type'." userInfo:nil]; + return [self initWithPath:@"" type:YYKVStorageTypeFile]; +} + +- (instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type { + if (path.length == 0 || path.length > kPathLengthMax) { + NSLog(@"YYKVStorage init error: invalid path: [%@].", path); + return nil; + } + if (type > YYKVStorageTypeMixed) { + NSLog(@"YYKVStorage init error: invalid type: %lu.", (unsigned long)type); + return nil; + } + + self = [super init]; + _path = path.copy; + _type = type; + _dataPath = [path stringByAppendingPathComponent:kDataDirectoryName]; + _trashPath = [path stringByAppendingPathComponent:kTrashDirectoryName]; + _trashQueue = dispatch_queue_create("com.ibireme.cache.disk.trash", DISPATCH_QUEUE_SERIAL); + _dbPath = [path stringByAppendingPathComponent:kDBFileName]; + _errorLogsEnabled = YES; + NSError *error = nil; + if (![[NSFileManager defaultManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:nil + error:&error] || + ![[NSFileManager defaultManager] createDirectoryAtPath:[path stringByAppendingPathComponent:kDataDirectoryName] + withIntermediateDirectories:YES + attributes:nil + error:&error] || + ![[NSFileManager defaultManager] createDirectoryAtPath:[path stringByAppendingPathComponent:kTrashDirectoryName] + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + NSLog(@"YYKVStorage init error:%@", error); + return nil; + } + + if (![self _dbOpen] || ![self _dbInitialize]) { + // db file may broken... + [self _dbClose]; + [self _reset]; // rebuild + if (![self _dbOpen] || ![self _dbInitialize]) { + [self _dbClose]; + NSLog(@"YYKVStorage init error: fail to open sqlite db."); + return nil; + } + } + [self _fileEmptyTrashInBackground]; // empty the trash if failed at last time + return self; +} + +- (void)dealloc { + UIBackgroundTaskIdentifier taskID = [_YYSharedApplication() beginBackgroundTaskWithExpirationHandler:^{}]; + [self _dbClose]; + if (taskID != UIBackgroundTaskInvalid) { + [_YYSharedApplication() endBackgroundTask:taskID]; + } +} + +- (BOOL)saveItem:(YYKVStorageItem *)item { + return [self saveItemWithKey:item.key value:item.value filename:item.filename extendedData:item.extendedData]; +} + +- (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value { + return [self saveItemWithKey:key value:value filename:nil extendedData:nil]; +} + +- (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value filename:(NSString *)filename extendedData:(NSData *)extendedData { + if (key.length == 0 || value.length == 0) return NO; + if (_type == YYKVStorageTypeFile && filename.length == 0) { + return NO; + } + + if (filename.length) { + if (![self _fileWriteWithName:filename data:value]) { + return NO; + } + if (![self _dbSaveWithKey:key value:value fileName:filename extendedData:extendedData]) { + [self _fileDeleteWithName:filename]; + return NO; + } + return YES; + } else { + if (_type != YYKVStorageTypeSQLite) { + NSString *filename = [self _dbGetFilenameWithKey:key]; + if (filename) { + [self _fileDeleteWithName:filename]; + } + } + return [self _dbSaveWithKey:key value:value fileName:nil extendedData:extendedData]; + } +} + +- (BOOL)removeItemForKey:(NSString *)key { + if (key.length == 0) return NO; + switch (_type) { + case YYKVStorageTypeSQLite: { + return [self _dbDeleteItemWithKey:key]; + } break; + case YYKVStorageTypeFile: + case YYKVStorageTypeMixed: { + NSString *filename = [self _dbGetFilenameWithKey:key]; + if (filename) { + [self _fileDeleteWithName:filename]; + } + return [self _dbDeleteItemWithKey:key]; + } break; + default: return NO; + } +} + +- (BOOL)removeItemForKeys:(NSArray *)keys { + if (keys.count == 0) return NO; + switch (_type) { + case YYKVStorageTypeSQLite: { + return [self _dbDeleteItemWithKeys:keys]; + } break; + case YYKVStorageTypeFile: + case YYKVStorageTypeMixed: { + NSArray *filenames = [self _dbGetFilenameWithKeys:keys]; + for (NSString *filename in filenames) { + [self _fileDeleteWithName:filename]; + } + return [self _dbDeleteItemWithKeys:keys]; + } break; + default: return NO; + } +} + +- (BOOL)removeItemsLargerThanSize:(int)size { + if (size == INT_MAX) return YES; + if (size <= 0) return [self removeAllItems]; + + switch (_type) { + case YYKVStorageTypeSQLite: { + if ([self _dbDeleteItemsWithSizeLargerThan:size]) { + [self _dbCheckpoint]; + return YES; + } + } break; + case YYKVStorageTypeFile: + case YYKVStorageTypeMixed: { + NSArray *filenames = [self _dbGetFilenamesWithSizeLargerThan:size]; + for (NSString *name in filenames) { + [self _fileDeleteWithName:name]; + } + if ([self _dbDeleteItemsWithSizeLargerThan:size]) { + [self _dbCheckpoint]; + return YES; + } + } break; + } + return NO; +} + +- (BOOL)removeItemsEarlierThanTime:(int)time { + if (time <= 0) return YES; + if (time == INT_MAX) return [self removeAllItems]; + + switch (_type) { + case YYKVStorageTypeSQLite: { + if ([self _dbDeleteItemsWithTimeEarlierThan:time]) { + [self _dbCheckpoint]; + return YES; + } + } break; + case YYKVStorageTypeFile: + case YYKVStorageTypeMixed: { + NSArray *filenames = [self _dbGetFilenamesWithTimeEarlierThan:time]; + for (NSString *name in filenames) { + [self _fileDeleteWithName:name]; + } + if ([self _dbDeleteItemsWithTimeEarlierThan:time]) { + [self _dbCheckpoint]; + return YES; + } + } break; + } + return NO; +} + +- (BOOL)removeItemsToFitSize:(int)maxSize { + if (maxSize == INT_MAX) return YES; + if (maxSize <= 0) return [self removeAllItems]; + + int total = [self _dbGetTotalItemSize]; + if (total < 0) return NO; + if (total <= maxSize) return YES; + + NSArray *items = nil; + BOOL suc = NO; + do { + int perCount = 16; + items = [self _dbGetItemSizeInfoOrderByTimeAscWithLimit:perCount]; + for (YYKVStorageItem *item in items) { + if (total > maxSize) { + if (item.filename) { + [self _fileDeleteWithName:item.filename]; + } + suc = [self _dbDeleteItemWithKey:item.key]; + total -= item.size; + } else { + break; + } + if (!suc) break; + } + } while (total > maxSize && items.count > 0 && suc); + if (suc) [self _dbCheckpoint]; + return suc; +} + +- (BOOL)removeItemsToFitCount:(int)maxCount { + if (maxCount == INT_MAX) return YES; + if (maxCount <= 0) return [self removeAllItems]; + + int total = [self _dbGetTotalItemCount]; + if (total < 0) return NO; + if (total <= maxCount) return YES; + + NSArray *items = nil; + BOOL suc = NO; + do { + int perCount = 16; + items = [self _dbGetItemSizeInfoOrderByTimeAscWithLimit:perCount]; + for (YYKVStorageItem *item in items) { + if (total > maxCount) { + if (item.filename) { + [self _fileDeleteWithName:item.filename]; + } + suc = [self _dbDeleteItemWithKey:item.key]; + total--; + } else { + break; + } + if (!suc) break; + } + } while (total > maxCount && items.count > 0 && suc); + if (suc) [self _dbCheckpoint]; + return suc; +} + +- (BOOL)removeAllItems { + if (![self _dbClose]) return NO; + [self _reset]; + if (![self _dbOpen]) return NO; + if (![self _dbInitialize]) return NO; + return YES; +} + +- (void)removeAllItemsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress + endBlock:(void(^)(BOOL error))end { + + int total = [self _dbGetTotalItemCount]; + if (total <= 0) { + if (end) end(total < 0); + } else { + int left = total; + int perCount = 32; + NSArray *items = nil; + BOOL suc = NO; + do { + items = [self _dbGetItemSizeInfoOrderByTimeAscWithLimit:perCount]; + for (YYKVStorageItem *item in items) { + if (left > 0) { + if (item.filename) { + [self _fileDeleteWithName:item.filename]; + } + suc = [self _dbDeleteItemWithKey:item.key]; + left--; + } else { + break; + } + if (!suc) break; + } + if (progress) progress(total - left, total); + } while (left > 0 && items.count > 0 && suc); + if (suc) [self _dbCheckpoint]; + if (end) end(!suc); + } +} + +- (YYKVStorageItem *)getItemForKey:(NSString *)key { + if (key.length == 0) return nil; + YYKVStorageItem *item = [self _dbGetItemWithKey:key excludeInlineData:NO]; + if (item) { + [self _dbUpdateAccessTimeWithKey:key]; + if (item.filename) { + item.value = [self _fileReadWithName:item.filename]; + if (!item.value) { + [self _dbDeleteItemWithKey:key]; + item = nil; + } + } + } + return item; +} + +- (YYKVStorageItem *)getItemInfoForKey:(NSString *)key { + if (key.length == 0) return nil; + YYKVStorageItem *item = [self _dbGetItemWithKey:key excludeInlineData:YES]; + return item; +} + +- (NSData *)getItemValueForKey:(NSString *)key { + if (key.length == 0) return nil; + NSData *value = nil; + switch (_type) { + case YYKVStorageTypeFile: { + NSString *filename = [self _dbGetFilenameWithKey:key]; + if (filename) { + value = [self _fileReadWithName:filename]; + if (!value) { + [self _dbDeleteItemWithKey:key]; + value = nil; + } + } + } break; + case YYKVStorageTypeSQLite: { + value = [self _dbGetValueWithKey:key]; + } break; + case YYKVStorageTypeMixed: { + NSString *filename = [self _dbGetFilenameWithKey:key]; + if (filename) { + value = [self _fileReadWithName:filename]; + if (!value) { + [self _dbDeleteItemWithKey:key]; + value = nil; + } + } else { + value = [self _dbGetValueWithKey:key]; + } + } break; + } + if (value) { + [self _dbUpdateAccessTimeWithKey:key]; + } + return value; +} + +- (NSArray *)getItemForKeys:(NSArray *)keys { + if (keys.count == 0) return nil; + NSMutableArray *items = [self _dbGetItemWithKeys:keys excludeInlineData:NO]; + if (_type != YYKVStorageTypeSQLite) { + for (NSInteger i = 0, max = items.count; i < max; i++) { + YYKVStorageItem *item = items[i]; + if (item.filename) { + item.value = [self _fileReadWithName:item.filename]; + if (!item.value) { + if (item.key) [self _dbDeleteItemWithKey:item.key]; + [items removeObjectAtIndex:i]; + i--; + max--; + } + } + } + } + if (items.count > 0) { + [self _dbUpdateAccessTimeWithKeys:keys]; + } + return items.count ? items : nil; +} + +- (NSArray *)getItemInfoForKeys:(NSArray *)keys { + if (keys.count == 0) return nil; + return [self _dbGetItemWithKeys:keys excludeInlineData:YES]; +} + +- (NSDictionary *)getItemValueForKeys:(NSArray *)keys { + NSMutableArray *items = (NSMutableArray *)[self getItemForKeys:keys]; + NSMutableDictionary *kv = [NSMutableDictionary new]; + for (YYKVStorageItem *item in items) { + if (item.key && item.value) { + [kv setObject:item.value forKey:item.key]; + } + } + return kv.count ? kv : nil; +} + +- (BOOL)itemExistsForKey:(NSString *)key { + if (key.length == 0) return NO; + return [self _dbGetItemCountWithKey:key] > 0; +} + +- (int)getItemsCount { + return [self _dbGetTotalItemCount]; +} + +- (int)getItemsSize { + return [self _dbGetTotalItemSize]; +} + +@end diff --git a/Demo/Pods/YYCache/YYCache/YYMemoryCache.h b/Demo/Pods/YYCache/YYCache/YYMemoryCache.h new file mode 100644 index 00000000..ded84402 --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYMemoryCache.h @@ -0,0 +1,213 @@ +// +// YYMemoryCache.h +// 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 + +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 diff --git a/Demo/Pods/YYCache/YYCache/YYMemoryCache.m b/Demo/Pods/YYCache/YYCache/YYMemoryCache.m new file mode 100644 index 00000000..9042d9b1 --- /dev/null +++ b/Demo/Pods/YYCache/YYCache/YYMemoryCache.m @@ -0,0 +1,505 @@ +// +// YYMemoryCache.m +// 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 "YYMemoryCache.h" +#import +#import +#import +#import + + +static inline dispatch_queue_t YYMemoryCacheGetReleaseQueue() { + return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); +} + +/** + A node in linked map. + Typically, you should not use this class directly. + */ +@interface _YYLinkedMapNode : NSObject { + @package + __unsafe_unretained _YYLinkedMapNode *_prev; // retained by dic + __unsafe_unretained _YYLinkedMapNode *_next; // retained by dic + id _key; + id _value; + NSUInteger _cost; + NSTimeInterval _time; +} +@end + +@implementation _YYLinkedMapNode +@end + + +/** + A linked map used by YYMemoryCache. + It's not thread-safe and does not validate the parameters. + + Typically, you should not use this class directly. + */ +@interface _YYLinkedMap : NSObject { + @package + CFMutableDictionaryRef _dic; // do not set object directly + NSUInteger _totalCost; + NSUInteger _totalCount; + _YYLinkedMapNode *_head; // MRU, do not change it directly + _YYLinkedMapNode *_tail; // LRU, do not change it directly + BOOL _releaseOnMainThread; + BOOL _releaseAsynchronously; +} + +/// Insert a node at head and update the total cost. +/// Node and node.key should not be nil. +- (void)insertNodeAtHead:(_YYLinkedMapNode *)node; + +/// Bring a inner node to header. +/// Node should already inside the dic. +- (void)bringNodeToHead:(_YYLinkedMapNode *)node; + +/// Remove a inner node and update the total cost. +/// Node should already inside the dic. +- (void)removeNode:(_YYLinkedMapNode *)node; + +/// Remove tail node if exist. +- (_YYLinkedMapNode *)removeTailNode; + +/// Remove all node in background queue. +- (void)removeAll; + +@end + +@implementation _YYLinkedMap + +- (instancetype)init { + self = [super init]; + _dic = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + _releaseOnMainThread = NO; + _releaseAsynchronously = YES; + return self; +} + +- (void)dealloc { + CFRelease(_dic); +} + +- (void)insertNodeAtHead:(_YYLinkedMapNode *)node { + CFDictionarySetValue(_dic, (__bridge const void *)(node->_key), (__bridge const void *)(node)); + _totalCost += node->_cost; + _totalCount++; + if (_head) { + node->_next = _head; + _head->_prev = node; + _head = node; + } else { + _head = _tail = node; + } +} + +- (void)bringNodeToHead:(_YYLinkedMapNode *)node { + if (_head == node) return; + + if (_tail == node) { + _tail = node->_prev; + _tail->_next = nil; + } else { + node->_next->_prev = node->_prev; + node->_prev->_next = node->_next; + } + node->_next = _head; + node->_prev = nil; + _head->_prev = node; + _head = node; +} + +- (void)removeNode:(_YYLinkedMapNode *)node { + CFDictionaryRemoveValue(_dic, (__bridge const void *)(node->_key)); + _totalCost -= node->_cost; + _totalCount--; + if (node->_next) node->_next->_prev = node->_prev; + if (node->_prev) node->_prev->_next = node->_next; + if (_head == node) _head = node->_next; + if (_tail == node) _tail = node->_prev; +} + +- (_YYLinkedMapNode *)removeTailNode { + if (!_tail) return nil; + _YYLinkedMapNode *tail = _tail; + CFDictionaryRemoveValue(_dic, (__bridge const void *)(_tail->_key)); + _totalCost -= _tail->_cost; + _totalCount--; + if (_head == _tail) { + _head = _tail = nil; + } else { + _tail = _tail->_prev; + _tail->_next = nil; + } + return tail; +} + +- (void)removeAll { + _totalCost = 0; + _totalCount = 0; + _head = nil; + _tail = nil; + if (CFDictionaryGetCount(_dic) > 0) { + CFMutableDictionaryRef holder = _dic; + _dic = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + if (_releaseAsynchronously) { + dispatch_queue_t queue = _releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); + dispatch_async(queue, ^{ + CFRelease(holder); // hold and release in specified queue + }); + } else if (_releaseOnMainThread && !pthread_main_np()) { + dispatch_async(dispatch_get_main_queue(), ^{ + CFRelease(holder); // hold and release in specified queue + }); + } else { + CFRelease(holder); + } + } +} + +@end + + + +@implementation YYMemoryCache { + pthread_mutex_t _lock; + _YYLinkedMap *_lru; + dispatch_queue_t _queue; +} + +- (void)_trimRecursively { + __weak typeof(self) _self = self; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + __strong typeof(_self) self = _self; + if (!self) return; + [self _trimInBackground]; + [self _trimRecursively]; + }); +} + +- (void)_trimInBackground { + dispatch_async(_queue, ^{ + [self _trimToCost:self->_costLimit]; + [self _trimToCount:self->_countLimit]; + [self _trimToAge:self->_ageLimit]; + }); +} + +- (void)_trimToCost:(NSUInteger)costLimit { + BOOL finish = NO; + pthread_mutex_lock(&_lock); + if (costLimit == 0) { + [_lru removeAll]; + finish = YES; + } else if (_lru->_totalCost <= costLimit) { + finish = YES; + } + pthread_mutex_unlock(&_lock); + if (finish) return; + + NSMutableArray *holder = [NSMutableArray new]; + while (!finish) { + if (pthread_mutex_trylock(&_lock) == 0) { + if (_lru->_totalCost > costLimit) { + _YYLinkedMapNode *node = [_lru removeTailNode]; + if (node) [holder addObject:node]; + } else { + finish = YES; + } + pthread_mutex_unlock(&_lock); + } else { + usleep(10 * 1000); //10 ms + } + } + if (holder.count) { + dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); + dispatch_async(queue, ^{ + [holder count]; // release in queue + }); + } +} + +- (void)_trimToCount:(NSUInteger)countLimit { + BOOL finish = NO; + pthread_mutex_lock(&_lock); + if (countLimit == 0) { + [_lru removeAll]; + finish = YES; + } else if (_lru->_totalCount <= countLimit) { + finish = YES; + } + pthread_mutex_unlock(&_lock); + if (finish) return; + + NSMutableArray *holder = [NSMutableArray new]; + while (!finish) { + if (pthread_mutex_trylock(&_lock) == 0) { + if (_lru->_totalCount > countLimit) { + _YYLinkedMapNode *node = [_lru removeTailNode]; + if (node) [holder addObject:node]; + } else { + finish = YES; + } + pthread_mutex_unlock(&_lock); + } else { + usleep(10 * 1000); //10 ms + } + } + if (holder.count) { + dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); + dispatch_async(queue, ^{ + [holder count]; // release in queue + }); + } +} + +- (void)_trimToAge:(NSTimeInterval)ageLimit { + BOOL finish = NO; + NSTimeInterval now = CACurrentMediaTime(); + pthread_mutex_lock(&_lock); + if (ageLimit <= 0) { + [_lru removeAll]; + finish = YES; + } else if (!_lru->_tail || (now - _lru->_tail->_time) <= ageLimit) { + finish = YES; + } + pthread_mutex_unlock(&_lock); + if (finish) return; + + NSMutableArray *holder = [NSMutableArray new]; + while (!finish) { + if (pthread_mutex_trylock(&_lock) == 0) { + if (_lru->_tail && (now - _lru->_tail->_time) > ageLimit) { + _YYLinkedMapNode *node = [_lru removeTailNode]; + if (node) [holder addObject:node]; + } else { + finish = YES; + } + pthread_mutex_unlock(&_lock); + } else { + usleep(10 * 1000); //10 ms + } + } + if (holder.count) { + dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); + dispatch_async(queue, ^{ + [holder count]; // release in queue + }); + } +} + +- (void)_appDidReceiveMemoryWarningNotification { + if (self.didReceiveMemoryWarningBlock) { + self.didReceiveMemoryWarningBlock(self); + } + if (self.shouldRemoveAllObjectsOnMemoryWarning) { + [self removeAllObjects]; + } +} + +- (void)_appDidEnterBackgroundNotification { + if (self.didEnterBackgroundBlock) { + self.didEnterBackgroundBlock(self); + } + if (self.shouldRemoveAllObjectsWhenEnteringBackground) { + [self removeAllObjects]; + } +} + +#pragma mark - public + +- (instancetype)init { + self = super.init; + pthread_mutex_init(&_lock, NULL); + _lru = [_YYLinkedMap new]; + _queue = dispatch_queue_create("com.ibireme.cache.memory", DISPATCH_QUEUE_SERIAL); + + _countLimit = NSUIntegerMax; + _costLimit = NSUIntegerMax; + _ageLimit = DBL_MAX; + _autoTrimInterval = 5.0; + _shouldRemoveAllObjectsOnMemoryWarning = YES; + _shouldRemoveAllObjectsWhenEnteringBackground = YES; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidReceiveMemoryWarningNotification) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidEnterBackgroundNotification) name:UIApplicationDidEnterBackgroundNotification object:nil]; + + [self _trimRecursively]; + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; + [_lru removeAll]; + pthread_mutex_destroy(&_lock); +} + +- (NSUInteger)totalCount { + pthread_mutex_lock(&_lock); + NSUInteger count = _lru->_totalCount; + pthread_mutex_unlock(&_lock); + return count; +} + +- (NSUInteger)totalCost { + pthread_mutex_lock(&_lock); + NSUInteger totalCost = _lru->_totalCost; + pthread_mutex_unlock(&_lock); + return totalCost; +} + +- (BOOL)releaseOnMainThread { + pthread_mutex_lock(&_lock); + BOOL releaseOnMainThread = _lru->_releaseOnMainThread; + pthread_mutex_unlock(&_lock); + return releaseOnMainThread; +} + +- (void)setReleaseOnMainThread:(BOOL)releaseOnMainThread { + pthread_mutex_lock(&_lock); + _lru->_releaseOnMainThread = releaseOnMainThread; + pthread_mutex_unlock(&_lock); +} + +- (BOOL)releaseAsynchronously { + pthread_mutex_lock(&_lock); + BOOL releaseAsynchronously = _lru->_releaseAsynchronously; + pthread_mutex_unlock(&_lock); + return releaseAsynchronously; +} + +- (void)setReleaseAsynchronously:(BOOL)releaseAsynchronously { + pthread_mutex_lock(&_lock); + _lru->_releaseAsynchronously = releaseAsynchronously; + pthread_mutex_unlock(&_lock); +} + +- (BOOL)containsObjectForKey:(id)key { + if (!key) return NO; + pthread_mutex_lock(&_lock); + BOOL contains = CFDictionaryContainsKey(_lru->_dic, (__bridge const void *)(key)); + pthread_mutex_unlock(&_lock); + return contains; +} + +- (id)objectForKey:(id)key { + if (!key) return nil; + pthread_mutex_lock(&_lock); + _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key)); + if (node) { + node->_time = CACurrentMediaTime(); + [_lru bringNodeToHead:node]; + } + pthread_mutex_unlock(&_lock); + return node ? node->_value : nil; +} + +- (void)setObject:(id)object forKey:(id)key { + [self setObject:object forKey:key withCost:0]; +} + +- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost { + if (!key) return; + if (!object) { + [self removeObjectForKey:key]; + return; + } + pthread_mutex_lock(&_lock); + _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key)); + NSTimeInterval now = CACurrentMediaTime(); + if (node) { + _lru->_totalCost -= node->_cost; + _lru->_totalCost += cost; + node->_cost = cost; + node->_time = now; + node->_value = object; + [_lru bringNodeToHead:node]; + } else { + node = [_YYLinkedMapNode new]; + node->_cost = cost; + node->_time = now; + node->_key = key; + node->_value = object; + [_lru insertNodeAtHead:node]; + } + if (_lru->_totalCost > _costLimit) { + dispatch_async(_queue, ^{ + [self trimToCost:_costLimit]; + }); + } + if (_lru->_totalCount > _countLimit) { + _YYLinkedMapNode *node = [_lru removeTailNode]; + if (_lru->_releaseAsynchronously) { + dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); + dispatch_async(queue, ^{ + [node class]; //hold and release in queue + }); + } else if (_lru->_releaseOnMainThread && !pthread_main_np()) { + dispatch_async(dispatch_get_main_queue(), ^{ + [node class]; //hold and release in queue + }); + } + } + pthread_mutex_unlock(&_lock); +} + +- (void)removeObjectForKey:(id)key { + if (!key) return; + pthread_mutex_lock(&_lock); + _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key)); + if (node) { + [_lru removeNode:node]; + if (_lru->_releaseAsynchronously) { + dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); + dispatch_async(queue, ^{ + [node class]; //hold and release in queue + }); + } else if (_lru->_releaseOnMainThread && !pthread_main_np()) { + dispatch_async(dispatch_get_main_queue(), ^{ + [node class]; //hold and release in queue + }); + } + } + pthread_mutex_unlock(&_lock); +} + +- (void)removeAllObjects { + pthread_mutex_lock(&_lock); + [_lru removeAll]; + pthread_mutex_unlock(&_lock); +} + +- (void)trimToCount:(NSUInteger)count { + if (count == 0) { + [self removeAllObjects]; + return; + } + [self _trimToCount:count]; +} + +- (void)trimToCost:(NSUInteger)cost { + [self _trimToCost:cost]; +} + +- (void)trimToAge:(NSTimeInterval)age { + [self _trimToAge:age]; +} + +- (NSString *)description { + if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _name]; + else return [NSString stringWithFormat:@"<%@: %p>", self.class, self]; +} + +@end diff --git a/Demo/XMNetworkingDemo.xcodeproj/project.pbxproj b/Demo/XMNetworkingDemo.xcodeproj/project.pbxproj index 1a4857f1..6386f566 100644 --- a/Demo/XMNetworkingDemo.xcodeproj/project.pbxproj +++ b/Demo/XMNetworkingDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1A45E6D82106B6F300D939EF /* XMCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 1A45E6D72106B6F300D939EF /* XMCache.m */; }; 4B16DFA7208B7E4B00BF7AC5 /* NetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B16DFA6208B7E4B00BF7AC5 /* NetworkManager.m */; }; 4B16DFAA208B7FFB00BF7AC5 /* TipSetTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B16DFA9208B7FFB00BF7AC5 /* TipSetTableViewCell.m */; }; 4B16DFAD208B89F100BF7AC5 /* TipSetItemModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B16DFAC208B89F100BF7AC5 /* TipSetItemModel.m */; }; @@ -43,6 +44,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1A45E6D62106B6F300D939EF /* XMCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XMCache.h; sourceTree = ""; }; + 1A45E6D72106B6F300D939EF /* XMCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XMCache.m; sourceTree = ""; }; 4B16DFA5208B7E4B00BF7AC5 /* NetworkManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NetworkManager.h; sourceTree = ""; }; 4B16DFA6208B7E4B00BF7AC5 /* NetworkManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NetworkManager.m; sourceTree = ""; }; 4B16DFA8208B7FFB00BF7AC5 /* TipSetTableViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TipSetTableViewCell.h; sourceTree = ""; }; @@ -196,6 +199,8 @@ 4BF801121DFED44300999C54 /* XMCenter.m */, 4BF801141DFED49500999C54 /* XMEngine.h */, 4BF801151DFED49500999C54 /* XMEngine.m */, + 1A45E6D62106B6F300D939EF /* XMCache.h */, + 1A45E6D72106B6F300D939EF /* XMCache.m */, ); name = XMNetworking; path = ../XMNetworking; @@ -341,6 +346,7 @@ 4B16DFB0208C94E500BF7AC5 /* SearchViewController.m in Sources */, 4B16DFAA208B7FFB00BF7AC5 /* TipSetTableViewCell.m in Sources */, 4BF800D21DFED15C00999C54 /* AppDelegate.m in Sources */, + 1A45E6D82106B6F300D939EF /* XMCache.m in Sources */, 4B16DFAD208B89F100BF7AC5 /* TipSetItemModel.m in Sources */, 4BD09BC62087A789003591F4 /* MainViewController.m in Sources */, 4BF800CF1DFED15C00999C54 /* main.m in Sources */, diff --git a/XMNetworking/XMCache.h b/XMNetworking/XMCache.h new file mode 100644 index 00000000..765684c0 --- /dev/null +++ b/XMNetworking/XMCache.h @@ -0,0 +1,37 @@ +// +// XMCache.h +// XMNetworkingDemo +// +// Created by 一只皮卡丘 on 2018/7/24. +// Copyright © 2018年 XMNetworking. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN +@interface XMCache : NSObject + ++ (instancetype)cache; + ++ (void)clearAllCache; + ++ (__nullable id)getRequestCacheByUrl:(NSString *)url; + ++ (void)cacheDataInMemory:(id)data withKey:(NSString *)key; + ++ (void)cacheDataInDisk:(id)data withKey:(NSString *)key; + ++ (void)cacheDataInMemoryAndDisk:(id)data withKey:(NSString *)key; + +- (void)clearAllCache; + +- (__nullable id)getRequestCacheByUrl:(NSString *)url; + +- (void)cacheDataInMemory:(id)data withKey:(NSString *)key; + +- (void)cacheDataInDisk:(id)data withKey:(NSString *)key; + +- (void)cacheDataInMemoryAndDisk:(id)data withKey:(NSString *)key; + +@end +NS_ASSUME_NONNULL_END diff --git a/XMNetworking/XMCache.m b/XMNetworking/XMCache.m new file mode 100644 index 00000000..e39b438c --- /dev/null +++ b/XMNetworking/XMCache.m @@ -0,0 +1,86 @@ +// +// XMCache.m +// XMNetworkingDemo +// +// Created by 一只皮卡丘 on 2018/7/24. +// Copyright © 2018年 XMNetworking. All rights reserved. +// + +#import "XMCache.h" +#import + +@implementation XMCache +{ + YYCache *_cache; +} + ++ (instancetype)cache +{ + static id sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[XMCache alloc] init]; + }); + return sharedInstance; +} + +- (instancetype)init +{ + self = [super init]; + if (self) { + _cache = [YYCache cacheWithName:@"XMNetworkingCache"]; + } + return self; +} + +- (void)clearAllCache +{ + [_cache removeAllObjects]; +} + +- (__nullable id)getRequestCacheByUrl:(NSString *)url +{ + return [_cache objectForKey:url]; +} + +- (void)cacheDataInMemory:(id)data withKey:(NSString *)key +{ + [_cache.memoryCache setObject:data forKey:key]; +} + +- (void)cacheDataInDisk:(id)data withKey:(NSString *)key +{ + [_cache.diskCache setObject:data forKey:key]; +} + +- (void)cacheDataInMemoryAndDisk:(id)data withKey:(NSString *)key +{ + [_cache setObject:data forKey:key]; +} + ++ (void)clearAllCache +{ + [[XMCache cache] clearAllCache]; +} + ++ (__nullable id)getRequestCacheByUrl:(NSString *)url +{ + return [[XMCache cache] getRequestCacheByUrl:url]; +} + ++ (void)cacheDataInMemory:(id)data withKey:(NSString *)key +{ + return [[XMCache cache] cacheDataInMemory:data withKey:key]; +} + ++ (void)cacheDataInDisk:(id)data withKey:(NSString *)key +{ + return [[XMCache cache] cacheDataInDisk:data withKey:key]; +} + ++ (void)cacheDataInMemoryAndDisk:(id)data withKey:(NSString *)key +{ + return [[XMCache cache] cacheDataInMemoryAndDisk:data withKey:key]; +} + +@end diff --git a/XMNetworking/XMCenter.m b/XMNetworking/XMCenter.m index 395636af..168c7ddb 100644 --- a/XMNetworking/XMCenter.m +++ b/XMNetworking/XMCenter.m @@ -9,6 +9,7 @@ #import "XMCenter.h" #import "XMRequest.h" #import "XMEngine.h" +#import "XMCache.h" @interface XMCenter () { dispatch_semaphore_t _lock; @@ -149,11 +150,32 @@ - (NSString *)sendRequest:(XMRequestConfigBlock)configBlock XM_SAFE_BLOCK(configBlock, request); [self xm_processRequest:request onProgress:progressBlock onSuccess:successBlock onFailure:failureBlock onFinished:finishedBlock]; - [self xm_sendRequest:request]; + [self xm_sendRequestWithCachePolicy:request]; return request.identifier; } +- (void)xm_sendRequestWithCachePolicy:(XMRequest *)request { + if (request.requestCachePolicy == XMRequestCacheIgnoreCache) { + [self xm_sendRequest:request]; + } else { + NSString *cacheKey = [NSString stringWithFormat:@"%@%@",request.url,request.parameters]; + id cache = [XMCache getRequestCacheByUrl:cacheKey]; + if (cache != nil) { + if (request.successBlock) { + XM_SAFE_BLOCK(request.successBlock,cache); + } + if (request.finishedBlock) { + XM_SAFE_BLOCK(request.finishedBlock,cache,nil); + } + } + if ((request.requestCachePolicy == XMRequestCacheCacheFirst && cache == nil) || + request.requestCachePolicy == XMRequestCacheCacheReload) { + [self xm_sendRequest:request]; + } + } +} + - (NSString *)sendBatchRequest:(XMBatchRequestConfigBlock)configBlock onSuccess:(nullable XMBCSuccessBlock)successBlock onFailure:(nullable XMBCFailureBlock)failureBlock @@ -526,6 +548,7 @@ - (void)xm_sendRequest:(XMRequest *)request { [self xm_failureWithError:error forRequest:request]; } else { [self xm_successWithResponse:responseObject forRequest:request]; + [self cacheResponseByRequest:request response:responseObject]; } }]; } @@ -617,6 +640,29 @@ - (NSString *)xm_identifierForBatchAndChainRequest { return identifier; } +- (void)cacheResponseByRequest:(XMRequest *)request response:(id)responseObj { + NSString *cacheKey = [NSString stringWithFormat:@"%@%@",request.url,request.parameters]; + switch (request.responseCachePolicy) { + case XMResponseCacheNotCache: + break; + case XMResponseCacheCacheOnMemory: + { + [XMCache cacheDataInMemory:responseObj withKey:cacheKey]; + } + break; + case XMResponseCacheCacheOnDisk: + { + [XMCache cacheDataInDisk:responseObj withKey:cacheKey]; + } + break; + case XMResponseCacheCacheOnMemoryAndDisk: + { + [XMCache cacheDataInMemoryAndDisk:responseObj withKey:cacheKey]; + } + break; + } +} + #pragma mark - Accessor - (NSMutableDictionary *)runningBatchAndChainPool { diff --git a/XMNetworking/XMConst.h b/XMNetworking/XMConst.h index 86d5ba75..fff755b5 100644 --- a/XMNetworking/XMConst.h +++ b/XMNetworking/XMConst.h @@ -67,6 +67,19 @@ typedef NS_ENUM(NSInteger, XMNetworkConnectionType) { kXMNetworkConnectionTypeViaWiFi = 2, }; +typedef NS_ENUM(NSInteger, XMRequestCachePolicy) { + XMRequestCacheIgnoreCache = 0, // ignore cache + XMRequestCacheCacheFirst = 1, // If the cache hits, no request is sent, otherwise the request is sent. + XMRequestCacheCacheReload = 2, // If the cache hits, callback a cache and send a new request. Once the data is received, callback again. +}; + +typedef NS_ENUM(NSInteger, XMResponseCachePolicy) { + XMResponseCacheNotCache = 0, + XMResponseCacheCacheOnMemory = 1, + XMResponseCacheCacheOnDisk = 2, + XMResponseCacheCacheOnMemoryAndDisk = 3, +}; + ///------------------------------ /// @name XMRequest Config Blocks ///------------------------------ diff --git a/XMNetworking/XMRequest.h b/XMNetworking/XMRequest.h index d0dec7c1..d1cf1a26 100644 --- a/XMNetworking/XMRequest.h +++ b/XMNetworking/XMRequest.h @@ -78,6 +78,16 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign) XMResponseSerializerType responseSerializerType; +/** + cache policy for request, `XMRequestCacheIgnoreCache` by default, see `XMRequestCachePolicy` enum for details. + */ +@property (nonatomic, assign) XMRequestCachePolicy requestCachePolicy; + +/** + cache policy for response, `XMResponseCacheNotCache` by default, see `XMResponseCachePolicy` enum for details. + */ +@property (nonatomic, assign) XMResponseCachePolicy responseCachePolicy; + /** Timeout interval for request, `60` seconds by default. */