mirror of
https://github.com/zhigang1992/PINRemoteImage.git
synced 2026-01-12 22:49:34 +08:00
Updating example
This commit is contained in:
@@ -23,12 +23,12 @@ PODS:
|
||||
- libwebp/utils (0.5.0):
|
||||
- libwebp/core
|
||||
- libwebp/webp (0.5.0)
|
||||
- PINCache (2.2.2)
|
||||
- PINRemoteImage/Core (2.1.2):
|
||||
- PINCache (>= 2.1)
|
||||
- PINRemoteImage/iOS (2.1.2):
|
||||
- PINCache (3.0.0-beta)
|
||||
- PINRemoteImage/Core (3.0.0-beta.2):
|
||||
- PINCache (>= 3.0.0-beta)
|
||||
- PINRemoteImage/iOS (3.0.0-beta.2):
|
||||
- PINRemoteImage/Core
|
||||
- PINRemoteImage/WebP (2.1.2):
|
||||
- PINRemoteImage/WebP (3.0.0-beta.2):
|
||||
- libwebp
|
||||
- PINRemoteImage/Core
|
||||
|
||||
@@ -43,7 +43,7 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
libwebp: 68ba2001ba6806ee52837ebd77a551a0b6567e4e
|
||||
PINCache: 078426d356ab95ef875e9e62e5c35a2ea3333c28
|
||||
PINRemoteImage: 49c514f94a8a51ce871aebba2ea7e5a10598af3b
|
||||
PINCache: 9b66261ade3d4feb272df4b4dd2e035469909448
|
||||
PINRemoteImage: eb41cb4fa9c4434ca0911bddf1eb12e70a0b7f1f
|
||||
|
||||
COCOAPODS: 0.39.0
|
||||
|
||||
1
Example/Pods/Headers/Private/PINCache/PINCacheObjectSubscripting.h
generated
Symbolic link
1
Example/Pods/Headers/Private/PINCache/PINCacheObjectSubscripting.h
generated
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../PINCache/PINCache/PINCacheObjectSubscripting.h
|
||||
1
Example/Pods/Headers/Public/PINCache/PINCacheObjectSubscripting.h
generated
Symbolic link
1
Example/Pods/Headers/Public/PINCache/PINCacheObjectSubscripting.h
generated
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../PINCache/PINCache/PINCacheObjectSubscripting.h
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "PINRemoteImage",
|
||||
"version": "2.1.2",
|
||||
"version": "3.0.0-beta.2",
|
||||
"summary": "A thread safe, performant, feature rich image fetcher",
|
||||
"homepage": "https://github.com/pinterest/PINRemoteImage",
|
||||
"license": "Apache 2.0",
|
||||
@@ -9,12 +9,11 @@
|
||||
},
|
||||
"source": {
|
||||
"git": "https://github.com/pinterest/PINRemoteImage.git",
|
||||
"tag": "2.1.2"
|
||||
"tag": "3.0.0-beta.2"
|
||||
},
|
||||
"social_media_url": "https://twitter.com/garrettmoon",
|
||||
"platforms": {
|
||||
"ios": "6.0",
|
||||
"osx": "10.8",
|
||||
"ios": "7.0",
|
||||
"tvos": "9.0"
|
||||
},
|
||||
"requires_arc": true,
|
||||
@@ -22,6 +21,11 @@
|
||||
"subspecs": [
|
||||
{
|
||||
"name": "Core",
|
||||
"platforms": {
|
||||
"ios": "7.0",
|
||||
"tvos": "9.0",
|
||||
"osx": "10.9"
|
||||
},
|
||||
"source_files": "Pod/Classes/**/*.{h,m}",
|
||||
"exclude_files": [
|
||||
"Pod/Classes/Image Categories/FLAnimatedImageView+PINRemoteImage.h",
|
||||
@@ -34,13 +38,16 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"PINCache": [
|
||||
">=2.1"
|
||||
">=3.0.0-beta"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "iOS",
|
||||
"platforms": "ios",
|
||||
"platforms": {
|
||||
"ios": "7.0",
|
||||
"tvos": "9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"PINRemoteImage/Core": [
|
||||
|
||||
@@ -50,23 +57,26 @@
|
||||
},
|
||||
{
|
||||
"name": "OSX",
|
||||
"platforms": "osx",
|
||||
"platforms": {
|
||||
"osx": "10.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"PINRemoteImage/Core": [
|
||||
|
||||
]
|
||||
},
|
||||
"frameworks": "Cocoa"
|
||||
"frameworks": [
|
||||
"Cocoa",
|
||||
"CoreServices"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tvOS",
|
||||
"platforms": "tvos",
|
||||
"dependencies": {
|
||||
"PINRemoteImage/Core": [
|
||||
"PINRemoteImage/iOS": [
|
||||
|
||||
]
|
||||
},
|
||||
"frameworks": "UIKit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "FLAnimatedImage",
|
||||
|
||||
14
Example/Pods/Manifest.lock
generated
vendored
14
Example/Pods/Manifest.lock
generated
vendored
@@ -23,12 +23,12 @@ PODS:
|
||||
- libwebp/utils (0.5.0):
|
||||
- libwebp/core
|
||||
- libwebp/webp (0.5.0)
|
||||
- PINCache (2.2.2)
|
||||
- PINRemoteImage/Core (2.1.2):
|
||||
- PINCache (>= 2.1)
|
||||
- PINRemoteImage/iOS (2.1.2):
|
||||
- PINCache (3.0.0-beta)
|
||||
- PINRemoteImage/Core (3.0.0-beta.2):
|
||||
- PINCache (>= 3.0.0-beta)
|
||||
- PINRemoteImage/iOS (3.0.0-beta.2):
|
||||
- PINRemoteImage/Core
|
||||
- PINRemoteImage/WebP (2.1.2):
|
||||
- PINRemoteImage/WebP (3.0.0-beta.2):
|
||||
- libwebp
|
||||
- PINRemoteImage/Core
|
||||
|
||||
@@ -43,7 +43,7 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
libwebp: 68ba2001ba6806ee52837ebd77a551a0b6567e4e
|
||||
PINCache: 078426d356ab95ef875e9e62e5c35a2ea3333c28
|
||||
PINRemoteImage: 49c514f94a8a51ce871aebba2ea7e5a10598af3b
|
||||
PINCache: 9b66261ade3d4feb272df4b4dd2e035469909448
|
||||
PINRemoteImage: eb41cb4fa9c4434ca0911bddf1eb12e70a0b7f1f
|
||||
|
||||
COCOAPODS: 0.39.0
|
||||
|
||||
30
Example/Pods/PINCache/PINCache/PINCache.h
generated
30
Example/Pods/PINCache/PINCache/PINCache.h
generated
@@ -14,15 +14,19 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
A callback block which provides only the cache as an argument
|
||||
*/
|
||||
|
||||
typedef void (^PINCacheBlock)(PINCache *cache);
|
||||
|
||||
/**
|
||||
A callback block which provides the cache, key and object as arguments
|
||||
*/
|
||||
|
||||
typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullable object);
|
||||
|
||||
/**
|
||||
A callback block which provides a BOOL value as argument
|
||||
*/
|
||||
typedef void (^PINCacheObjectContainmentBlock)(BOOL containsObject);
|
||||
|
||||
|
||||
/**
|
||||
`PINCache` is a thread safe key/value store designed for persisting temporary objects that are expensive to
|
||||
reproduce, such as downloaded data or the results of slow processing. It is comprised of two self-similar
|
||||
@@ -40,7 +44,7 @@ typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullabl
|
||||
@warning when using in extension or watch extension, define PIN_APP_EXTENSIONS=1
|
||||
*/
|
||||
|
||||
@interface PINCache : NSObject
|
||||
@interface PINCache : NSObject <PINCacheObjectSubscripting>
|
||||
|
||||
#pragma mark -
|
||||
/// @name Core
|
||||
@@ -106,6 +110,17 @@ typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullabl
|
||||
#pragma mark -
|
||||
/// @name Asynchronous Methods
|
||||
|
||||
/**
|
||||
This method determines whether an object is present for the given key in the cache. This method returns immediately
|
||||
and executes the passed block after the object is available, potentially in parallel with other blocks on the
|
||||
<concurrentQueue>.
|
||||
|
||||
@see containsObjectForKey:
|
||||
@param key The key associated with the object.
|
||||
@param block A block to be executed concurrently after the containment check happened
|
||||
*/
|
||||
- (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block;
|
||||
|
||||
/**
|
||||
Retrieves the object for the specified key. This method returns immediately and executes the passed
|
||||
block after the object is available, potentially in parallel with other blocks on the <concurrentQueue>.
|
||||
@@ -154,6 +169,15 @@ typedef void (^PINCacheObjectBlock)(PINCache *cache, NSString *key, id __nullabl
|
||||
#pragma mark -
|
||||
/// @name Synchronous Methods
|
||||
|
||||
/**
|
||||
This method determines whether an object is present for the given key in the cache.
|
||||
|
||||
@see containsObjectForKey:block:
|
||||
@param key The key associated with the object.
|
||||
@result YES if an object is present for the given key in the cache, otherwise NO.
|
||||
*/
|
||||
- (BOOL)containsObjectForKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
Retrieves the object for the specified key. This method blocks the calling thread until the object is available.
|
||||
Uses a semaphore to achieve synchronicity on the disk cache.
|
||||
|
||||
59
Example/Pods/PINCache/PINCache/PINCache.m
generated
59
Example/Pods/PINCache/PINCache/PINCache.m
generated
@@ -46,7 +46,7 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
if (self = [super init]) {
|
||||
_name = [name copy];
|
||||
|
||||
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINCachePrefix, self];
|
||||
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINCachePrefix, (void *)self];
|
||||
_concurrentQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", queueName] UTF8String], DISPATCH_QUEUE_CONCURRENT);
|
||||
|
||||
_diskCache = [[PINDiskCache alloc] initWithName:_name rootPath:rootPath];
|
||||
@@ -57,7 +57,7 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINCachePrefix, _name, self];
|
||||
return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINCachePrefix, _name, (void *)self];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedCache
|
||||
@@ -74,6 +74,22 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
|
||||
#pragma mark - Public Asynchronous Methods -
|
||||
|
||||
- (void)containsObjectForKey:(NSString *)key block:(PINCacheObjectContainmentBlock)block
|
||||
{
|
||||
if (!key || !block) {
|
||||
return;
|
||||
}
|
||||
|
||||
__weak PINCache *weakSelf = self;
|
||||
|
||||
dispatch_async(_concurrentQueue, ^{
|
||||
PINCache *strongSelf = weakSelf;
|
||||
|
||||
BOOL containsObject = [strongSelf containsObjectForKey:key];
|
||||
block(containsObject);
|
||||
});
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
|
||||
@@ -88,38 +104,27 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
PINCache *strongSelf = weakSelf;
|
||||
if (!strongSelf)
|
||||
return;
|
||||
|
||||
__weak PINCache *weakSelf = strongSelf;
|
||||
|
||||
[strongSelf->_memoryCache objectForKey:key block:^(PINMemoryCache *memoryCache, NSString *memoryCacheKey, id memoryCacheObject) {
|
||||
PINCache *strongSelf = weakSelf;
|
||||
if (!strongSelf)
|
||||
return;
|
||||
|
||||
if (memoryCacheObject) {
|
||||
[strongSelf->_diskCache fileURLForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> diskCacheObject, NSURL *fileURL) {
|
||||
// update the access time on disk
|
||||
}];
|
||||
|
||||
__weak PINCache *weakSelf = strongSelf;
|
||||
|
||||
[strongSelf->_diskCache fileURLForKey:memoryCacheKey block:NULL];
|
||||
dispatch_async(strongSelf->_concurrentQueue, ^{
|
||||
PINCache *strongSelf = weakSelf;
|
||||
if (strongSelf)
|
||||
block(strongSelf, memoryCacheKey, memoryCacheObject);
|
||||
});
|
||||
} else {
|
||||
__weak PINCache *weakSelf = strongSelf;
|
||||
|
||||
[strongSelf->_diskCache objectForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> diskCacheObject, NSURL *fileURL) {
|
||||
[strongSelf->_diskCache objectForKey:memoryCacheKey block:^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> diskCacheObject) {
|
||||
PINCache *strongSelf = weakSelf;
|
||||
if (!strongSelf)
|
||||
return;
|
||||
|
||||
[strongSelf->_memoryCache setObject:diskCacheObject forKey:diskCacheKey block:nil];
|
||||
|
||||
__weak PINCache *weakSelf = strongSelf;
|
||||
|
||||
|
||||
dispatch_async(strongSelf->_concurrentQueue, ^{
|
||||
PINCache *strongSelf = weakSelf;
|
||||
if (strongSelf)
|
||||
@@ -151,7 +156,7 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
dispatch_group_leave(group);
|
||||
};
|
||||
|
||||
diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> memoryCacheObject, NSURL *memoryCacheFileURL) {
|
||||
diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> memoryCacheObject) {
|
||||
dispatch_group_leave(group);
|
||||
};
|
||||
}
|
||||
@@ -191,7 +196,7 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
dispatch_group_leave(group);
|
||||
};
|
||||
|
||||
diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> memoryCacheObject, NSURL *memoryCacheFileURL) {
|
||||
diskBlock = ^(PINDiskCache *diskCache, NSString *diskCacheKey, id <NSCoding> memoryCacheObject) {
|
||||
dispatch_group_leave(group);
|
||||
};
|
||||
}
|
||||
@@ -303,6 +308,14 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
- (BOOL)containsObjectForKey:(NSString *)key
|
||||
{
|
||||
if (!key)
|
||||
return NO;
|
||||
|
||||
return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key];
|
||||
}
|
||||
|
||||
- (__nullable id)objectForKey:(NSString *)key
|
||||
{
|
||||
if (!key)
|
||||
@@ -332,6 +345,16 @@ static NSString * const PINCacheSharedName = @"PINCacheShared";
|
||||
[_diskCache setObject:object forKey:key];
|
||||
}
|
||||
|
||||
- (id)objectForKeyedSubscript:(NSString *)key
|
||||
{
|
||||
return [self objectForKey:key];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key
|
||||
{
|
||||
[self setObject:obj forKey:key];
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(NSString *)key
|
||||
{
|
||||
if (!key)
|
||||
|
||||
31
Example/Pods/PINCache/PINCache/PINCacheObjectSubscripting.h
generated
Normal file
31
Example/Pods/PINCache/PINCache/PINCacheObjectSubscripting.h
generated
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// PINCacheObjectSubscripting.h
|
||||
// PINCache
|
||||
//
|
||||
// Created by Rocir Marcos Leite Santiago on 4/2/16.
|
||||
// Copyright © 2016 Pinterest. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@protocol PINCacheObjectSubscripting <NSObject>
|
||||
|
||||
@required
|
||||
|
||||
/**
|
||||
This method enables using literals on the receiving object, such as `id object = cache[@"key"];`.
|
||||
|
||||
@param key The key associated with the object.
|
||||
@result The object for the specified key.
|
||||
*/
|
||||
- (id)objectForKeyedSubscript:(NSString *)key;
|
||||
|
||||
/**
|
||||
This method enables using literals on the receiving object, such as `cache[@"key"] = object;`.
|
||||
|
||||
@param object An object to be assigned for the key.
|
||||
@param key A key to associate with the object. This string will be copied.
|
||||
*/
|
||||
- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key;
|
||||
|
||||
@end
|
||||
82
Example/Pods/PINCache/PINCache/PINDiskCache.h
generated
82
Example/Pods/PINCache/PINCache/PINDiskCache.h
generated
@@ -5,6 +5,8 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Nullability.h"
|
||||
|
||||
#import "PINCacheObjectSubscripting.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class PINDiskCache;
|
||||
@@ -12,14 +14,23 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
A callback block which provides only the cache as an argument
|
||||
*/
|
||||
|
||||
typedef void (^PINDiskCacheBlock)(PINDiskCache *cache);
|
||||
|
||||
/**
|
||||
A callback block which provides the cache, key and object as arguments
|
||||
*/
|
||||
typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <NSCoding> __nullable object);
|
||||
|
||||
/**
|
||||
A callback block which provides the key and fileURL of the object
|
||||
*/
|
||||
typedef void (^PINDiskCacheFileURLBlock)(NSString *key, NSURL * __nullable fileURL);
|
||||
|
||||
/**
|
||||
A callback block which provides a BOOL value as argument
|
||||
*/
|
||||
typedef void (^PINDiskCacheContainsBlock)(BOOL containsObject);
|
||||
|
||||
typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <NSCoding> __nullable object, NSURL * __nullable fileURL);
|
||||
|
||||
/**
|
||||
`PINDiskCache` is a thread safe key/value store backed by the file system. It accepts any object conforming
|
||||
@@ -44,7 +55,7 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
<ageLimit> will trigger a GCD timer to periodically to trim the cache with <trimToDate:>.
|
||||
*/
|
||||
|
||||
@interface PINDiskCache : NSObject
|
||||
@interface PINDiskCache : NSObject <PINCacheObjectSubscripting>
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +79,7 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
The total number of bytes used on disk, as reported by `NSURLTotalFileAllocatedSizeKey`.
|
||||
|
||||
@warning This property should only be read from a call to <synchronouslyLockFileAccessWhileExecutingBlock:> or
|
||||
its asynchronous equivolent <lockFileAccessWhileExecutingBlock:>
|
||||
its asynchronous equivalent <lockFileAccessWhileExecutingBlock:>
|
||||
|
||||
For example:
|
||||
|
||||
@@ -97,6 +108,21 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
*/
|
||||
@property (assign) NSTimeInterval ageLimit;
|
||||
|
||||
|
||||
/**
|
||||
The writing protection option used when writing a file on disk. This value is used every time an object is set.
|
||||
NSDataWritingAtomic and NSDataWritingWithoutOverwriting are ignored if set
|
||||
Defaults to NSDataWritingFileProtectionNone.
|
||||
|
||||
@warning Only new files are affected by the new writing protection. If you need all files to be affected,
|
||||
you'll have to purge and set the objects back to the cache
|
||||
|
||||
Only available on iOS
|
||||
*/
|
||||
#if TARGET_OS_IPHONE
|
||||
@property (assign) NSDataWritingOptions writingProtectionOption;
|
||||
#endif
|
||||
|
||||
/**
|
||||
If ttlCache is YES, the cache behaves like a ttlCache. This means that once an object enters the
|
||||
cache, it only lives as long as self.ageLimit. This has the following implications:
|
||||
@@ -191,12 +217,21 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
*/
|
||||
- (void)lockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block;
|
||||
|
||||
/**
|
||||
This method determines whether an object is present for the given key in the cache. This method returns immediately
|
||||
and executes the passed block after the object is available, potentially in parallel with other blocks on the
|
||||
<concurrentQueue>.
|
||||
|
||||
@see containsObjectForKey:
|
||||
@param key The key associated with the object.
|
||||
@param block A block to be executed concurrently after the containment check happened
|
||||
*/
|
||||
- (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block;
|
||||
|
||||
/**
|
||||
Retrieves the object for the specified key. This method returns immediately and executes the passed
|
||||
block as soon as the object is available.
|
||||
|
||||
@warning The fileURL is only valid for the duration of this block, do not use it after the block ends.
|
||||
|
||||
@param key The key associated with the requested object.
|
||||
@param block A block to be executed serially when the object is available.
|
||||
*/
|
||||
@@ -209,10 +244,15 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
@warning Access is protected for the duration of the block, but to maintain safe disk access do not
|
||||
access this fileURL after the block has ended.
|
||||
|
||||
@warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache
|
||||
or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is
|
||||
*not* passed the instance of the disk cache. You should also avoid doing extensive work while this
|
||||
lock is held.
|
||||
|
||||
@param key The key associated with the requested object.
|
||||
@param block A block to be executed serially when the file URL is available.
|
||||
*/
|
||||
- (void)fileURLForKey:(nullable NSString *)key block:(nullable PINDiskCacheObjectBlock)block;
|
||||
- (void)fileURLForKey:(NSString *)key block:(nullable PINDiskCacheFileURLBlock)block;
|
||||
|
||||
/**
|
||||
Stores an object in the cache for the specified key. This method returns immediately and executes the
|
||||
@@ -276,8 +316,14 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
|
||||
@param block A block to be executed for every object in the cache.
|
||||
@param completionBlock An optional block to be executed after the enumeration is complete.
|
||||
|
||||
@warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache
|
||||
or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is
|
||||
*not* passed the instance of the disk cache. You should also avoid doing extensive work while this
|
||||
lock is held.
|
||||
|
||||
*/
|
||||
- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock;
|
||||
- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block completionBlock:(nullable PINDiskCacheBlock)completionBlock;
|
||||
|
||||
#pragma mark -
|
||||
/// @name Synchronous Methods
|
||||
@@ -292,6 +338,15 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
*/
|
||||
- (void)synchronouslyLockFileAccessWhileExecutingBlock:(nullable PINDiskCacheBlock)block;
|
||||
|
||||
/**
|
||||
This method determines whether an object is present for the given key in the cache.
|
||||
|
||||
@see containsObjectForKey:block:
|
||||
@param key The key associated with the object.
|
||||
@result YES if an object is present for the given key in the cache, otherwise NO.
|
||||
*/
|
||||
- (BOOL)containsObjectForKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
Retrieves the object for the specified key. This method blocks the calling thread until the
|
||||
object is available.
|
||||
@@ -311,7 +366,7 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
@param key The key associated with the object.
|
||||
@result The file URL for the specified key.
|
||||
*/
|
||||
- (NSURL *)fileURLForKey:(nullable NSString *)key;
|
||||
- (nullable NSURL *)fileURLForKey:(nullable NSString *)key;
|
||||
|
||||
/**
|
||||
Stores an object in the cache for the specified key. This method blocks the calling thread until
|
||||
@@ -363,10 +418,17 @@ typedef void (^PINDiskCacheObjectBlock)(PINDiskCache *cache, NSString *key, id <
|
||||
read from disk, the `object` parameter of the block will be `nil` but the `fileURL` will be available.
|
||||
This method blocks the calling thread until all objects have been enumerated.
|
||||
@param block A block to be executed for every object in the cache.
|
||||
|
||||
@warning Do not call this method within the event blocks (<didRemoveObjectBlock>, etc.)
|
||||
Instead use the asynchronous version, <enumerateObjectsWithBlock:completionBlock:>.
|
||||
|
||||
@warning The PINDiskCache lock is held while block is executed. Any synchronous calls to the diskcache
|
||||
or a cache which owns the instance of the disk cache are likely to cause a deadlock. This is why the block is
|
||||
*not* passed the instance of the disk cache. You should also avoid doing extensive work while this
|
||||
lock is held.
|
||||
|
||||
*/
|
||||
- (void)enumerateObjectsWithBlock:(nullable PINDiskCacheObjectBlock)block;
|
||||
- (void)enumerateObjectsWithBlock:(nullable PINDiskCacheFileURLBlock)block;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
500
Example/Pods/PINCache/PINCache/PINDiskCache.m
generated
500
Example/Pods/PINCache/PINCache/PINDiskCache.m
generated
@@ -8,6 +8,8 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
#import <pthread.h>
|
||||
|
||||
#define PINDiskCacheError(error) if (error) { NSLog(@"%@ (%d) ERROR: %@", \
|
||||
[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
|
||||
__LINE__, [error localizedDescription]); }
|
||||
@@ -15,24 +17,21 @@ __LINE__, [error localizedDescription]); }
|
||||
static NSString * const PINDiskCachePrefix = @"com.pinterest.PINDiskCache";
|
||||
static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
|
||||
@interface PINBackgroundTask : NSObject
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH
|
||||
@property (atomic, assign) UIBackgroundTaskIdentifier taskID;
|
||||
#endif
|
||||
+ (instancetype)start;
|
||||
- (void)end;
|
||||
@end
|
||||
typedef NS_ENUM(NSUInteger, PINDiskCacheCondition) {
|
||||
PINDiskCacheConditionNotReady = 0,
|
||||
PINDiskCacheConditionReady = 1,
|
||||
};
|
||||
|
||||
@interface PINDiskCache ()
|
||||
@interface PINDiskCache () {
|
||||
NSConditionLock *_instanceLock;
|
||||
}
|
||||
|
||||
@property (assign) NSUInteger byteCount;
|
||||
@property (strong, nonatomic) NSURL *cacheURL;
|
||||
#if OS_OBJECT_USE_OBJC
|
||||
@property (strong, nonatomic) dispatch_queue_t asyncQueue;
|
||||
@property (strong, nonatomic) dispatch_semaphore_t lockSemaphore;
|
||||
#else
|
||||
@property (assign, nonatomic) dispatch_queue_t asyncQueue;
|
||||
@property (assign, nonatomic) dispatch_semaphore_t lockSemaphore;
|
||||
#endif
|
||||
@property (strong, nonatomic) NSMutableDictionary *dates;
|
||||
@property (strong, nonatomic) NSMutableDictionary *sizes;
|
||||
@@ -50,12 +49,15 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
@synthesize ageLimit = _ageLimit;
|
||||
@synthesize ttlCache = _ttlCache;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
@synthesize writingProtectionOption = _writingProtectionOption;
|
||||
#endif
|
||||
|
||||
#pragma mark - Initialization -
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
#if !OS_OBJECT_USE_OBJC
|
||||
dispatch_release(_lockSemaphore);
|
||||
dispatch_release(_asyncQueue);
|
||||
_asyncQueue = nil;
|
||||
#endif
|
||||
@@ -80,7 +82,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
if (self = [super init]) {
|
||||
_name = [name copy];
|
||||
_asyncQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@ Asynchronous Queue", PINDiskCachePrefix] UTF8String], DISPATCH_QUEUE_CONCURRENT);
|
||||
_lockSemaphore = dispatch_semaphore_create(1);
|
||||
_instanceLock = [[NSConditionLock alloc] initWithCondition:PINDiskCacheConditionNotReady];
|
||||
_willAddObjectBlock = nil;
|
||||
_willRemoveObjectBlock = nil;
|
||||
_willRemoveAllObjectsBlock = nil;
|
||||
@@ -91,7 +93,11 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
_byteCount = 0;
|
||||
_byteLimit = 0;
|
||||
_ageLimit = 0.0;
|
||||
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
_writingProtectionOption = NSDataWritingFileProtectionNone;
|
||||
#endif
|
||||
|
||||
_dates = [[NSMutableDictionary alloc] init];
|
||||
_sizes = [[NSMutableDictionary alloc] init];
|
||||
|
||||
@@ -99,13 +105,12 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
_cacheURL = [NSURL fileURLWithPathComponents:@[ rootPath, pathComponent ]];
|
||||
|
||||
//we don't want to do anything without setting up the disk cache, but we also don't want to block init, it can take a while to initialize
|
||||
//this is only safe because we use a dispatch_semaphore as a lock. If we switch to an NSLock or posix locks, this will *no longer be safe*.
|
||||
[self lock];
|
||||
dispatch_async(_asyncQueue, ^{
|
||||
[self createCacheDirectory];
|
||||
[self initializeDiskProperties];
|
||||
|
||||
[self unlock];
|
||||
//should always be able to aquire the lock unless the below code is running.
|
||||
[_instanceLock lockWhenCondition:PINDiskCacheConditionNotReady];
|
||||
[self _locked_createCacheDirectory];
|
||||
[self _locked_initializeDiskProperties];
|
||||
[_instanceLock unlockWithCondition:PINDiskCacheConditionReady];
|
||||
});
|
||||
}
|
||||
return self;
|
||||
@@ -113,7 +118,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINDiskCachePrefix, _name, self];
|
||||
return [[NSString alloc] initWithFormat:@"%@.%@.%p", PINDiskCachePrefix, _name, (void *)self];
|
||||
}
|
||||
|
||||
+ (instancetype)sharedCache
|
||||
@@ -130,7 +135,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
|
||||
#pragma mark - Private Methods -
|
||||
|
||||
- (NSURL *)encodedFileURLForKey:(NSString *)key
|
||||
- (NSURL *)_locked_encodedFileURLForKey:(NSString *)key
|
||||
{
|
||||
if (![key length])
|
||||
return nil;
|
||||
@@ -243,8 +248,6 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
|
||||
+ (void)emptyTrash
|
||||
{
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
dispatch_async([self sharedTrashQueue], ^{
|
||||
NSError *searchTrashedItemsError = nil;
|
||||
NSArray *trashedItems = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:[self sharedTrashURL]
|
||||
@@ -258,14 +261,12 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[[NSFileManager defaultManager] removeItemAtURL:trashedItemURL error:&removeTrashedItemError];
|
||||
PINDiskCacheError(removeTrashedItemError);
|
||||
}
|
||||
|
||||
[task end];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private Queue Methods -
|
||||
|
||||
- (BOOL)createCacheDirectory
|
||||
- (BOOL)_locked_createCacheDirectory
|
||||
{
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[_cacheURL path]])
|
||||
return NO;
|
||||
@@ -280,7 +281,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
return success;
|
||||
}
|
||||
|
||||
- (void)initializeDiskProperties
|
||||
- (void)_locked_initializeDiskProperties
|
||||
{
|
||||
NSUInteger byteCount = 0;
|
||||
NSArray *keys = @[ NSURLContentModificationDateKey, NSURLTotalFileAllocatedSizeKey ];
|
||||
@@ -314,7 +315,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
self.byteCount = byteCount; // atomic
|
||||
}
|
||||
|
||||
- (BOOL)setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL
|
||||
- (BOOL)_locked_setFileModificationDate:(NSDate *)date forURL:(NSURL *)fileURL
|
||||
{
|
||||
if (!date || !fileURL) {
|
||||
return NO;
|
||||
@@ -338,77 +339,112 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
|
||||
- (BOOL)removeFileAndExecuteBlocksForKey:(NSString *)key
|
||||
{
|
||||
NSURL *fileURL = [self encodedFileURLForKey:key];
|
||||
if (!fileURL || ![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]])
|
||||
return NO;
|
||||
[self lock];
|
||||
NSURL *fileURL = [self _locked_encodedFileURLForKey:key];
|
||||
|
||||
if (_willRemoveObjectBlock)
|
||||
_willRemoveObjectBlock(self, key, nil, fileURL);
|
||||
if (!fileURL || ![[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
|
||||
[self unlock];
|
||||
return NO;
|
||||
}
|
||||
|
||||
BOOL trashed = [PINDiskCache moveItemAtURLToTrash:fileURL];
|
||||
if (!trashed)
|
||||
return NO;
|
||||
PINDiskCacheObjectBlock willRemoveObjectBlock = _willRemoveObjectBlock;
|
||||
if (willRemoveObjectBlock) {
|
||||
[self unlock];
|
||||
willRemoveObjectBlock(self, key, nil);
|
||||
[self lock];
|
||||
}
|
||||
|
||||
BOOL trashed = [PINDiskCache moveItemAtURLToTrash:fileURL];
|
||||
if (!trashed) {
|
||||
[self unlock];
|
||||
return NO;
|
||||
}
|
||||
|
||||
[PINDiskCache emptyTrash];
|
||||
[PINDiskCache emptyTrash];
|
||||
|
||||
NSNumber *byteSize = [_sizes objectForKey:key];
|
||||
if (byteSize)
|
||||
self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic
|
||||
|
||||
[_sizes removeObjectForKey:key];
|
||||
[_dates removeObjectForKey:key];
|
||||
|
||||
NSNumber *byteSize = [_sizes objectForKey:key];
|
||||
if (byteSize)
|
||||
self.byteCount = _byteCount - [byteSize unsignedIntegerValue]; // atomic
|
||||
PINDiskCacheObjectBlock didRemoveObjectBlock = _didRemoveObjectBlock;
|
||||
if (didRemoveObjectBlock) {
|
||||
[self unlock];
|
||||
_didRemoveObjectBlock(self, key, nil);
|
||||
[self lock];
|
||||
}
|
||||
|
||||
[_sizes removeObjectForKey:key];
|
||||
[_dates removeObjectForKey:key];
|
||||
|
||||
if (_didRemoveObjectBlock)
|
||||
_didRemoveObjectBlock(self, key, nil, fileURL);
|
||||
[self unlock];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)trimDiskToSize:(NSUInteger)trimByteCount
|
||||
{
|
||||
if (_byteCount <= trimByteCount)
|
||||
return;
|
||||
|
||||
NSArray *keysSortedBySize = [_sizes keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
|
||||
if (_byteCount <= trimByteCount)
|
||||
break;
|
||||
}
|
||||
[self lock];
|
||||
if (_byteCount > trimByteCount) {
|
||||
NSArray *keysSortedBySize = [_sizes keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
for (NSString *key in [keysSortedBySize reverseObjectEnumerator]) { // largest objects first
|
||||
[self unlock];
|
||||
|
||||
//unlock, removeFileAndExecuteBlocksForKey handles locking itself
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
|
||||
[self lock];
|
||||
|
||||
if (_byteCount <= trimByteCount)
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self unlock];
|
||||
}
|
||||
|
||||
- (void)trimDiskToSizeByDate:(NSUInteger)trimByteCount
|
||||
{
|
||||
if (_byteCount <= trimByteCount)
|
||||
return;
|
||||
|
||||
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
for (NSString *key in keysSortedByDate) { // oldest objects first
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
|
||||
if (_byteCount <= trimByteCount)
|
||||
break;
|
||||
}
|
||||
[self lock];
|
||||
if (_byteCount > trimByteCount) {
|
||||
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
for (NSString *key in keysSortedByDate) { // oldest objects first
|
||||
[self unlock];
|
||||
|
||||
//unlock, removeFileAndExecuteBlocksForKey handles locking itself
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
|
||||
[self lock];
|
||||
|
||||
if (_byteCount <= trimByteCount)
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self unlock];
|
||||
}
|
||||
|
||||
- (void)trimDiskToDate:(NSDate *)trimDate
|
||||
{
|
||||
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
for (NSString *key in keysSortedByDate) { // oldest files first
|
||||
NSDate *accessDate = [_dates objectForKey:key];
|
||||
if (!accessDate)
|
||||
continue;
|
||||
[self lock];
|
||||
NSArray *keysSortedByDate = [_dates keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
} else {
|
||||
break;
|
||||
for (NSString *key in keysSortedByDate) { // oldest files first
|
||||
NSDate *accessDate = [_dates objectForKey:key];
|
||||
if (!accessDate)
|
||||
continue;
|
||||
|
||||
if ([accessDate compare:trimDate] == NSOrderedAscending) { // older than trim date
|
||||
[self unlock];
|
||||
|
||||
//unlock, removeFileAndExecuteBlocksForKey handles locking itself
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
|
||||
[self lock];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[self unlock];
|
||||
}
|
||||
|
||||
- (void)trimToAgeLimitRecursively
|
||||
@@ -419,10 +455,8 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
if (ageLimit == 0.0)
|
||||
return;
|
||||
|
||||
[self lock];
|
||||
NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit];
|
||||
[self trimDiskToDate:date];
|
||||
[self unlock];
|
||||
NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:-ageLimit];
|
||||
[self trimDiskToDate:date];
|
||||
|
||||
__weak PINDiskCache *weakSelf = self;
|
||||
|
||||
@@ -449,6 +483,19 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
});
|
||||
}
|
||||
|
||||
- (void)containsObjectForKey:(NSString *)key block:(PINDiskCacheContainsBlock)block
|
||||
{
|
||||
if (!key || !block)
|
||||
return;
|
||||
|
||||
__weak PINDiskCache *weakSelf = self;
|
||||
|
||||
dispatch_async(_asyncQueue, ^{
|
||||
PINDiskCache *strongSelf = weakSelf;
|
||||
block([strongSelf containsObjectForKey:key]);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)objectForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block
|
||||
{
|
||||
__weak PINDiskCache *weakSelf = self;
|
||||
@@ -459,14 +506,12 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
id <NSCoding> object = [strongSelf objectForKey:key fileURL:&fileURL];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf, key, object, fileURL);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf, key, object);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)fileURLForKey:(NSString *)key block:(PINDiskCacheObjectBlock)block
|
||||
- (void)fileURLForKey:(NSString *)key block:(PINDiskCacheFileURLBlock)block
|
||||
{
|
||||
__weak PINDiskCache *weakSelf = self;
|
||||
|
||||
@@ -476,7 +521,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf, key, nil, fileURL);
|
||||
block(key, fileURL);
|
||||
[strongSelf unlock];
|
||||
}
|
||||
});
|
||||
@@ -492,9 +537,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf setObject:object forKey:key fileURL:&fileURL];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf, key, object, fileURL);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf, key, object);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -509,9 +552,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf removeObjectForKey:key fileURL:&fileURL];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf, key, nil, fileURL);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf, key, nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -525,9 +566,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf trimToSize:trimByteCount];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -541,9 +580,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf trimToDate:trimDate];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -557,9 +594,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf trimToSizeByDate:trimByteCount];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -573,14 +608,12 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf removeAllObjects];
|
||||
|
||||
if (block) {
|
||||
[strongSelf lock];
|
||||
block(strongSelf);
|
||||
[strongSelf unlock];
|
||||
block(strongSelf);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block completionBlock:(PINDiskCacheBlock)completionBlock
|
||||
- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block completionBlock:(PINDiskCacheBlock)completionBlock
|
||||
{
|
||||
__weak PINDiskCache *weakSelf = self;
|
||||
|
||||
@@ -589,9 +622,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[strongSelf enumerateObjectsWithBlock:block];
|
||||
|
||||
if (completionBlock) {
|
||||
[self lock];
|
||||
completionBlock(strongSelf);
|
||||
[self unlock];
|
||||
completionBlock(strongSelf);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -602,16 +633,26 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
{
|
||||
if (block) {
|
||||
[self lock];
|
||||
block(self);
|
||||
block(self);
|
||||
[self unlock];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)containsObjectForKey:(NSString *)key
|
||||
{
|
||||
return ([self fileURLForKey:key updateFileModificationDate:NO] != nil);
|
||||
}
|
||||
|
||||
- (__nullable id<NSCoding>)objectForKey:(NSString *)key
|
||||
{
|
||||
return [self objectForKey:key fileURL:nil];
|
||||
}
|
||||
|
||||
- (id)objectForKeyedSubscript:(NSString *)key
|
||||
{
|
||||
return [self objectForKey:key];
|
||||
}
|
||||
|
||||
- (__nullable id <NSCoding>)objectForKey:(NSString *)key fileURL:(NSURL **)outFileURL
|
||||
{
|
||||
NSDate *now = [[NSDate alloc] init];
|
||||
@@ -623,7 +664,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
NSURL *fileURL = nil;
|
||||
|
||||
[self lock];
|
||||
fileURL = [self encodedFileURLForKey:key];
|
||||
fileURL = [self _locked_encodedFileURLForKey:key];
|
||||
object = nil;
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]] &&
|
||||
@@ -638,7 +679,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
PINDiskCacheError(error);
|
||||
}
|
||||
if (!self->_ttlCache) {
|
||||
[self setFileModificationDate:now forURL:fileURL];
|
||||
[self _locked_setFileModificationDate:now forURL:fileURL];
|
||||
}
|
||||
}
|
||||
[self unlock];
|
||||
@@ -650,22 +691,28 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
return object;
|
||||
}
|
||||
|
||||
/// Helper function to call fileURLForKey:updateFileModificationDate:
|
||||
- (NSURL *)fileURLForKey:(NSString *)key
|
||||
{
|
||||
NSDate *now = [[NSDate alloc] init];
|
||||
|
||||
if (!key)
|
||||
// Don't update the file modification time, if self is a ttlCache
|
||||
return [self fileURLForKey:key updateFileModificationDate:!self->_ttlCache];
|
||||
}
|
||||
|
||||
- (NSURL *)fileURLForKey:(NSString *)key updateFileModificationDate:(BOOL)updateFileModificationDate
|
||||
{
|
||||
if (!key) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDate *now = [[NSDate alloc] init];
|
||||
NSURL *fileURL = nil;
|
||||
|
||||
[self lock];
|
||||
fileURL = [self encodedFileURLForKey:key];
|
||||
fileURL = [self _locked_encodedFileURLForKey:key];
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[fileURL path]]) {
|
||||
// Don't update the file modification time, if self is a ttlCache
|
||||
if (!self->_ttlCache) {
|
||||
[self setFileModificationDate:now forURL:fileURL];
|
||||
if (updateFileModificationDate) {
|
||||
[self _locked_setFileModificationDate:now forURL:fileURL];
|
||||
}
|
||||
} else {
|
||||
fileURL = nil;
|
||||
@@ -679,6 +726,11 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
[self setObject:object forKey:key fileURL:nil];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key
|
||||
{
|
||||
[self setObject:object forKey:key];
|
||||
}
|
||||
|
||||
- (void)setObject:(id <NSCoding>)object forKey:(NSString *)key fileURL:(NSURL **)outFileURL
|
||||
{
|
||||
NSDate *now = [[NSDate alloc] init];
|
||||
@@ -686,20 +738,32 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
if (!key || !object)
|
||||
return;
|
||||
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
NSDataWritingOptions writeOptions = NSDataWritingAtomic | self.writingProtectionOption;
|
||||
#else
|
||||
NSDataWritingOptions writeOptions = NSDataWritingAtomic;
|
||||
#endif
|
||||
|
||||
NSURL *fileURL = nil;
|
||||
|
||||
[self lock];
|
||||
fileURL = [self encodedFileURLForKey:key];
|
||||
|
||||
if (self->_willAddObjectBlock)
|
||||
self->_willAddObjectBlock(self, key, object, fileURL);
|
||||
|
||||
BOOL written = [NSKeyedArchiver archiveRootObject:object toFile:[fileURL path]];
|
||||
fileURL = [self _locked_encodedFileURLForKey:key];
|
||||
|
||||
PINDiskCacheObjectBlock willAddObjectBlock = self->_willAddObjectBlock;
|
||||
if (willAddObjectBlock) {
|
||||
[self unlock];
|
||||
willAddObjectBlock(self, key, object);
|
||||
[self lock];
|
||||
}
|
||||
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:object];
|
||||
NSError *writeError = nil;
|
||||
|
||||
BOOL written = [data writeToURL:fileURL options:writeOptions error:&writeError];
|
||||
PINDiskCacheError(writeError);
|
||||
|
||||
if (written) {
|
||||
[self setFileModificationDate:now forURL:fileURL];
|
||||
[self _locked_setFileModificationDate:now forURL:fileURL];
|
||||
|
||||
NSError *error = nil;
|
||||
NSDictionary *values = [fileURL resourceValuesForKeys:@[ NSURLTotalFileAllocatedSizeKey ] error:&error];
|
||||
@@ -720,16 +784,18 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
} else {
|
||||
fileURL = nil;
|
||||
}
|
||||
|
||||
if (self->_didAddObjectBlock)
|
||||
self->_didAddObjectBlock(self, key, object, written ? fileURL : nil);
|
||||
|
||||
PINDiskCacheObjectBlock didAddObjectBlock = self->_didAddObjectBlock;
|
||||
if (didAddObjectBlock) {
|
||||
[self unlock];
|
||||
didAddObjectBlock(self, key, object);
|
||||
[self lock];
|
||||
}
|
||||
[self unlock];
|
||||
|
||||
if (outFileURL) {
|
||||
*outFileURL = fileURL;
|
||||
}
|
||||
|
||||
[task end];
|
||||
}
|
||||
|
||||
- (void)removeObjectForKey:(NSString *)key
|
||||
@@ -742,16 +808,13 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
NSURL *fileURL = nil;
|
||||
|
||||
[self lock];
|
||||
fileURL = [self encodedFileURLForKey:key];
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
fileURL = [self _locked_encodedFileURLForKey:key];
|
||||
[self unlock];
|
||||
|
||||
[task end];
|
||||
[self removeFileAndExecuteBlocksForKey:key];
|
||||
|
||||
if (outFileURL) {
|
||||
*outFileURL = fileURL;
|
||||
@@ -765,13 +828,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
return;
|
||||
}
|
||||
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
[self lock];
|
||||
[self trimDiskToSize:trimByteCount];
|
||||
[self unlock];
|
||||
|
||||
[task end];
|
||||
[self trimDiskToSize:trimByteCount];
|
||||
}
|
||||
|
||||
- (void)trimToDate:(NSDate *)trimDate
|
||||
@@ -784,13 +841,7 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
return;
|
||||
}
|
||||
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
[self lock];
|
||||
[self trimDiskToDate:trimDate];
|
||||
[self unlock];
|
||||
|
||||
[task end];
|
||||
[self trimDiskToDate:trimDate];
|
||||
}
|
||||
|
||||
- (void)trimToSizeByDate:(NSUInteger)trimByteCount
|
||||
@@ -800,60 +851,55 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
return;
|
||||
}
|
||||
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
[self lock];
|
||||
[self trimDiskToSizeByDate:trimByteCount];
|
||||
[self unlock];
|
||||
|
||||
[task end];
|
||||
[self trimDiskToSizeByDate:trimByteCount];
|
||||
}
|
||||
|
||||
- (void)removeAllObjects
|
||||
{
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
[self lock];
|
||||
if (self->_willRemoveAllObjectsBlock)
|
||||
self->_willRemoveAllObjectsBlock(self);
|
||||
|
||||
PINDiskCacheBlock willRemoveAllObjectsBlock = self->_willRemoveAllObjectsBlock;
|
||||
if (willRemoveAllObjectsBlock) {
|
||||
[self unlock];
|
||||
willRemoveAllObjectsBlock(self);
|
||||
[self lock];
|
||||
}
|
||||
|
||||
[PINDiskCache moveItemAtURLToTrash:self->_cacheURL];
|
||||
[PINDiskCache emptyTrash];
|
||||
|
||||
[self createCacheDirectory];
|
||||
[self _locked_createCacheDirectory];
|
||||
|
||||
[self->_dates removeAllObjects];
|
||||
[self->_sizes removeAllObjects];
|
||||
self.byteCount = 0; // atomic
|
||||
|
||||
if (self->_didRemoveAllObjectsBlock)
|
||||
self->_didRemoveAllObjectsBlock(self);
|
||||
[self unlock];
|
||||
|
||||
[task end];
|
||||
PINDiskCacheBlock didRemoveAllObjectsBlock = self->_didRemoveAllObjectsBlock;
|
||||
if (didRemoveAllObjectsBlock) {
|
||||
[self unlock];
|
||||
didRemoveAllObjectsBlock(self);
|
||||
[self lock];
|
||||
}
|
||||
|
||||
[self unlock];
|
||||
}
|
||||
|
||||
- (void)enumerateObjectsWithBlock:(PINDiskCacheObjectBlock)block
|
||||
- (void)enumerateObjectsWithBlock:(PINDiskCacheFileURLBlock)block
|
||||
{
|
||||
if (!block)
|
||||
return;
|
||||
|
||||
PINBackgroundTask *task = [PINBackgroundTask start];
|
||||
|
||||
[self lock];
|
||||
NSDate *now = [NSDate date];
|
||||
NSArray *keysSortedByDate = [self->_dates keysSortedByValueUsingSelector:@selector(compare:)];
|
||||
|
||||
for (NSString *key in keysSortedByDate) {
|
||||
NSURL *fileURL = [self encodedFileURLForKey:key];
|
||||
NSURL *fileURL = [self _locked_encodedFileURLForKey:key];
|
||||
// If the cache should behave like a TTL cache, then only fetch the object if there's a valid ageLimit and the object is still alive
|
||||
if (!self->_ttlCache || self->_ageLimit <= 0 || fabs([[_dates objectForKey:key] timeIntervalSinceDate:now]) < self->_ageLimit) {
|
||||
block(self, key, nil, fileURL);
|
||||
block(key, fileURL);
|
||||
}
|
||||
}
|
||||
[self unlock];
|
||||
|
||||
[task end];
|
||||
}
|
||||
|
||||
#pragma mark - Public Thread Safe Accessors -
|
||||
@@ -1034,11 +1080,11 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
return;
|
||||
|
||||
[strongSelf lock];
|
||||
strongSelf->_byteLimit = byteLimit;
|
||||
strongSelf->_byteLimit = byteLimit;
|
||||
[strongSelf unlock];
|
||||
|
||||
if (byteLimit > 0)
|
||||
[strongSelf trimDiskToSizeByDate:byteLimit];
|
||||
[strongSelf unlock];
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1094,78 +1140,42 @@ static NSString * const PINDiskCacheSharedName = @"PINDiskCacheShared";
|
||||
});
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
- (NSDataWritingOptions)writingProtectionOption {
|
||||
NSDataWritingOptions option;
|
||||
|
||||
[self lock];
|
||||
option = _writingProtectionOption;
|
||||
[self unlock];
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
- (void)setWritingProtectionOption:(NSDataWritingOptions)writingProtectionOption {
|
||||
__weak PINDiskCache *weakSelf = self;
|
||||
|
||||
dispatch_async(_asyncQueue, ^{
|
||||
PINDiskCache *strongSelf = weakSelf;
|
||||
if (!strongSelf)
|
||||
return;
|
||||
|
||||
NSDataWritingOptions option = NSDataWritingFileProtectionMask & writingProtectionOption;
|
||||
|
||||
[strongSelf lock];
|
||||
strongSelf->_writingProtectionOption = option;
|
||||
[strongSelf unlock];
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)lock
|
||||
{
|
||||
dispatch_semaphore_wait(_lockSemaphore, DISPATCH_TIME_FOREVER);
|
||||
[_instanceLock lockWhenCondition:PINDiskCacheConditionReady];
|
||||
}
|
||||
|
||||
- (void)unlock
|
||||
{
|
||||
dispatch_semaphore_signal(_lockSemaphore);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation PINBackgroundTask
|
||||
|
||||
+ (BOOL)isAppExtension {
|
||||
|
||||
static BOOL isExtension;
|
||||
static dispatch_once_t onceToken;
|
||||
|
||||
dispatch_once(&onceToken, ^{
|
||||
NSDictionary *extensionDictionary = [[NSBundle mainBundle] infoDictionary][@"NSExtension"];
|
||||
isExtension = [extensionDictionary isKindOfClass:[NSDictionary class]];
|
||||
});
|
||||
|
||||
return isExtension;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH
|
||||
_taskID = UIBackgroundTaskInvalid;
|
||||
#endif
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)start
|
||||
{
|
||||
PINBackgroundTask *task = nil;
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH
|
||||
if ([self.class isAppExtension]) {
|
||||
return task;
|
||||
}
|
||||
|
||||
task = [[self alloc] init];
|
||||
|
||||
UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)];
|
||||
task.taskID = [sharedApplication beginBackgroundTaskWithExpirationHandler:^{
|
||||
UIBackgroundTaskIdentifier taskID = task.taskID;
|
||||
task.taskID = UIBackgroundTaskInvalid;
|
||||
[sharedApplication endBackgroundTask:taskID];
|
||||
}];
|
||||
#endif
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
- (void)end
|
||||
{
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_4_0 && !TARGET_OS_WATCH
|
||||
if ([self.class isAppExtension]) {
|
||||
return;
|
||||
}
|
||||
|
||||
UIBackgroundTaskIdentifier taskID = self.taskID;
|
||||
self.taskID = UIBackgroundTaskInvalid;
|
||||
|
||||
UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)];
|
||||
[sharedApplication endBackgroundTask:taskID];
|
||||
#endif
|
||||
[_instanceLock unlockWithCondition:PINDiskCacheConditionReady];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
31
Example/Pods/PINCache/PINCache/PINMemoryCache.h
generated
31
Example/Pods/PINCache/PINCache/PINMemoryCache.h
generated
@@ -5,6 +5,8 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Nullability.h"
|
||||
|
||||
#import "PINCacheObjectSubscripting.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class PINMemoryCache;
|
||||
@@ -12,7 +14,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/**
|
||||
A callback block which provides only the cache as an argument
|
||||
*/
|
||||
|
||||
typedef void (^PINMemoryCacheBlock)(PINMemoryCache *cache);
|
||||
|
||||
/**
|
||||
@@ -20,6 +21,12 @@ typedef void (^PINMemoryCacheBlock)(PINMemoryCache *cache);
|
||||
*/
|
||||
typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key, id __nullable object);
|
||||
|
||||
/**
|
||||
A callback block which provides a BOOL value as argument
|
||||
*/
|
||||
typedef void (^PINMemoryCacheContainmentBlock)(BOOL containsObject);
|
||||
|
||||
|
||||
/**
|
||||
`PINMemoryCache` is a fast, thread safe key/value store similar to `NSCache`. On iOS it will clear itself
|
||||
automatically to reduce memory usage when the app receives a memory warning or goes into the background.
|
||||
@@ -37,7 +44,7 @@ typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key,
|
||||
a memory cache backed by a disk cache.
|
||||
*/
|
||||
|
||||
@interface PINMemoryCache : NSObject
|
||||
@interface PINMemoryCache : NSObject <PINCacheObjectSubscripting>
|
||||
|
||||
#pragma mark -
|
||||
/// @name Core
|
||||
@@ -157,6 +164,17 @@ typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key,
|
||||
#pragma mark -
|
||||
/// @name Asynchronous Methods
|
||||
|
||||
/**
|
||||
This method determines whether an object is present for the given key in the cache. This method returns immediately
|
||||
and executes the passed block after the object is available, potentially in parallel with other blocks on the
|
||||
<concurrentQueue>.
|
||||
|
||||
@see containsObjectForKey:
|
||||
@param key The key associated with the object.
|
||||
@param block A block to be executed concurrently after the containment check happened
|
||||
*/
|
||||
- (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block;
|
||||
|
||||
/**
|
||||
Retrieves the object for the specified key. This method returns immediately and executes the passed
|
||||
block after the object is available, potentially in parallel with other blocks on the <concurrentQueue>.
|
||||
@@ -248,6 +266,15 @@ typedef void (^PINMemoryCacheObjectBlock)(PINMemoryCache *cache, NSString *key,
|
||||
#pragma mark -
|
||||
/// @name Synchronous Methods
|
||||
|
||||
/**
|
||||
This method determines whether an object is present for the given key in the cache.
|
||||
|
||||
@see containsObjectForKey:block:
|
||||
@param key The key associated with the object.
|
||||
@result YES if an object is present for the given key in the cache, otherwise NO.
|
||||
*/
|
||||
- (BOOL)containsObjectForKey:(NSString *)key;
|
||||
|
||||
/**
|
||||
Retrieves the object for the specified key. This method blocks the calling thread until the
|
||||
object is available.
|
||||
|
||||
42
Example/Pods/PINCache/PINCache/PINMemoryCache.m
generated
42
Example/Pods/PINCache/PINCache/PINMemoryCache.m
generated
@@ -55,7 +55,7 @@ static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache";
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_lockSemaphore = dispatch_semaphore_create(1);
|
||||
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINMemoryCachePrefix, self];
|
||||
NSString *queueName = [[NSString alloc] initWithFormat:@"%@.%p", PINMemoryCachePrefix, (void *)self];
|
||||
_concurrentQueue = dispatch_queue_create([queueName UTF8String], DISPATCH_QUEUE_CONCURRENT);
|
||||
|
||||
_dictionary = [[NSMutableDictionary alloc] init];
|
||||
@@ -270,6 +270,21 @@ static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache";
|
||||
|
||||
#pragma mark - Public Asynchronous Methods -
|
||||
|
||||
- (void)containsObjectForKey:(NSString *)key block:(PINMemoryCacheContainmentBlock)block
|
||||
{
|
||||
if (!key || !block)
|
||||
return;
|
||||
|
||||
__weak PINMemoryCache *weakSelf = self;
|
||||
|
||||
dispatch_async(_concurrentQueue, ^{
|
||||
PINMemoryCache *strongSelf = weakSelf;
|
||||
BOOL containsObject = [strongSelf containsObjectForKey:key];
|
||||
|
||||
block(containsObject);
|
||||
});
|
||||
}
|
||||
|
||||
- (void)objectForKey:(NSString *)key block:(PINMemoryCacheObjectBlock)block
|
||||
{
|
||||
__weak PINMemoryCache *weakSelf = self;
|
||||
@@ -381,6 +396,17 @@ static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache";
|
||||
|
||||
#pragma mark - Public Synchronous Methods -
|
||||
|
||||
- (BOOL)containsObjectForKey:(NSString *)key
|
||||
{
|
||||
if (!key)
|
||||
return NO;
|
||||
|
||||
[self lock];
|
||||
BOOL containsObject = (_dictionary[key] != nil);
|
||||
[self unlock];
|
||||
return containsObject;
|
||||
}
|
||||
|
||||
- (__nullable id)objectForKey:(NSString *)key
|
||||
{
|
||||
if (!key)
|
||||
@@ -404,11 +430,21 @@ static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache";
|
||||
return object;
|
||||
}
|
||||
|
||||
- (id)objectForKeyedSubscript:(NSString *)key
|
||||
{
|
||||
return [self objectForKey:key];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)object forKey:(NSString *)key
|
||||
{
|
||||
[self setObject:object forKey:key withCost:0];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)object forKeyedSubscript:(NSString *)key
|
||||
{
|
||||
[self setObject:object forKey:key];
|
||||
}
|
||||
|
||||
- (void)setObject:(id)object forKey:(NSString *)key withCost:(NSUInteger)cost
|
||||
{
|
||||
if (!key || !object)
|
||||
@@ -424,6 +460,10 @@ static NSString * const PINMemoryCachePrefix = @"com.pinterest.PINMemoryCache";
|
||||
willAddObjectBlock(self, key, object);
|
||||
|
||||
[self lock];
|
||||
NSNumber* oldCost = _costs[key];
|
||||
if (oldCost)
|
||||
_totalCost -= [oldCost unsignedIntegerValue];
|
||||
|
||||
_dictionary[key] = object;
|
||||
_dates[key] = [[NSDate alloc] init];
|
||||
_costs[key] = @(cost);
|
||||
|
||||
1
Example/Pods/PINCache/README.md
generated
1
Example/Pods/PINCache/README.md
generated
@@ -2,6 +2,7 @@
|
||||
|
||||
[](http://cocoadocs.org/docsets/PINCache/)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://travis-ci.org/pinterest/PINCache)
|
||||
|
||||
## Fast, non-deadlocking parallel object cache for iOS and OS X.
|
||||
|
||||
|
||||
4990
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
4990
Example/Pods/Pods.xcodeproj/project.pbxproj
generated
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
buildForArchiving = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = 'primary'
|
||||
BlueprintIdentifier = 'AA6EABED2EEE247391AC0B08'
|
||||
BlueprintIdentifier = 'F65F50CEFEC41C6C57DD53FD'
|
||||
BlueprintName = 'Pods-PINRemoteImage Tests-PINRemoteImage'
|
||||
ReferencedContainer = 'container:Pods.xcodeproj'
|
||||
BuildableName = 'libPods-PINRemoteImage Tests-PINRemoteImage.a'>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
buildForArchiving = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = 'primary'
|
||||
BlueprintIdentifier = 'C35373FC2E0A691023108168'
|
||||
BlueprintIdentifier = 'E6B9896E19DB3F7E3116F098'
|
||||
BlueprintName = 'Pods-PINRemoteImage-PINRemoteImage'
|
||||
ReferencedContainer = 'container:Pods.xcodeproj'
|
||||
BuildableName = 'libPods-PINRemoteImage-PINRemoteImage.a'>
|
||||
|
||||
Reference in New Issue
Block a user