NSCache
2019-09-30 本文已影响0人
Code_人生
- NSCache类
@interface NSCache <KeyType, ObjectType> : NSObject {
@private
id _delegate;
void *_private[5];
void *_reserved;
}
@property (copy) NSString *name;
@property (nullable, assign) id<NSCacheDelegate> delegate;
- (nullable ObjectType)objectForKey:(KeyType)key;
- (void)setObject:(ObjectType)obj forKey:(KeyType)key; // 0 cost
- (void)setObject:(ObjectType)obj forKey:(KeyType)key cost:(NSUInteger)g;
- (void)removeObjectForKey:(KeyType)key;
- (void)removeAllObjects;
@property NSUInteger totalCostLimit; // limits are imprecise/not strict
@property NSUInteger countLimit; // limits are imprecise/not strict
@property BOOL evictsObjectsWithDiscardedContent;
@end
- NSCacheDelegate协议
@protocol NSCacheDelegate <NSObject>
@optional
- (void)cache:(NSCache *)cache willEvictObject:(id)obj;
@end
一、NSCache特点
- 1、使用方便,类似字典
- 2、线程安全
- 3、内存不足,NSCache会自动释放存储对象
- 1.countLimit
- 2.手动调用 remove
- 3.app进入后台之后
- 4.收到内存警告的时候,不会释放存储对象
- 4、NSCache的 key 不会被拷贝,不需要实现 Coping 协议
- 5、先移除,后添加
_cache = [[NSCache alloc] init];
_cache.countLimit = 5;
_cache.delegate = self;
for (int i = 0; i < 9; i++) {
[_cache setObject:[NSString stringWithFormat:@"dengyazhou%d",i] forKey:[NSString stringWithFormat:@"DYZ%d",i]];
}
for (int i = 0; i < 12; i++) {
NSLog(@"Cache object:%@, at index :%d",[_cache objectForKey:[NSString stringWithFormat:@"DYZ%d",i]],i);
}
// countLimit,先移除,后添加
2019-09-05 14:17:01.198612+0800 LGTest[36708:7543575] obj:dengyazhou0 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:01.198757+0800 LGTest[36708:7543575] obj:dengyazhou1 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:01.198853+0800 LGTest[36708:7543575] obj:dengyazhou2 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:01.198951+0800 LGTest[36708:7543575] obj:dengyazhou3 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:01.199050+0800 LGTest[36708:7543575] Cache object:(null), at index :0
2019-09-05 14:17:01.199116+0800 LGTest[36708:7543575] Cache object:(null), at index :1
2019-09-05 14:17:01.199195+0800 LGTest[36708:7543575] Cache object:(null), at index :2
2019-09-05 14:17:01.199274+0800 LGTest[36708:7543575] Cache object:(null), at index :3
2019-09-05 14:17:01.199346+0800 LGTest[36708:7543575] Cache object:dengyazhou4, at index :4
2019-09-05 14:17:01.199422+0800 LGTest[36708:7543575] Cache object:dengyazhou5, at index :5
2019-09-05 14:17:01.199493+0800 LGTest[36708:7543575] Cache object:dengyazhou6, at index :6
2019-09-05 14:17:01.199551+0800 LGTest[36708:7543575] Cache object:dengyazhou7, at index :7
2019-09-05 14:17:01.199616+0800 LGTest[36708:7543575] Cache object:dengyazhou8, at index :8
2019-09-05 14:17:01.199695+0800 LGTest[36708:7543575] Cache object:(null), at index :9
2019-09-05 14:17:01.199805+0800 LGTest[36708:7543575] Cache object:(null), at index :10
2019-09-05 14:17:01.199928+0800 LGTest[36708:7543575] Cache object:(null), at index :11
// app进入后台之后,会移除
2019-09-05 14:17:11.128147+0800 LGTest[36708:7543575] obj:dengyazhou5 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:11.128278+0800 LGTest[36708:7543575] obj:dengyazhou6 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:11.128396+0800 LGTest[36708:7543575] obj:dengyazhou7 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:11.128545+0800 LGTest[36708:7543575] obj:dengyazhou8 will evict by Cache:<NSCache: 0x600002487080>
2019-09-05 14:17:11.128667+0800 LGTest[36708:7543575] obj:dengyazhou4 will evict by Cache:<NSCache: 0x600002487080>
二、模拟内存警告
- 添加
UIApplicationDidReceiveMemoryWarningNotification
通知观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dyz_didReceiveMemoryWaring:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
- 实现通知响应
- (void)dyz_didReceiveMemoryWaring:(NSNotification *)notification{
NSLog(@"notification----%@",notification);
[_testPurgeableData endContentAccess];
}
- 发送通知
点击模拟器菜单栏Debug
->Simulate Memory Warning
三、NSDiscardableContent
协议
- 提高缓存的淘汰
@protocol NSDiscardableContent
@required
- (BOOL)beginContentAccess;
- (void)endContentAccess;
- (void)discardContentIfPossible;
- (BOOL)isContentDiscarded;
@end
-
NSPurgeableData
实现了NSDiscardableContent
协议
@interface NSPurgeableData : NSMutableData <NSDiscardableContent> {
@private
NSUInteger _length;
int32_t _accessCount;
uint8_t _private[32];
void *_reserved;
}
@end
- 申请一块内存,如果没有空闲的内存,系统会把内存中的存储置换到磁盘上,这样就有可空闲的内存供我们使用了
- 实现了
NSDiscardableContent
协议的对象是可以直接被清除的,不用置换 - 往
NSCache
中添加对象,如果内存满了,NSCache
会把内存中的对象先保存到磁盘上,如果内存中的对象有实现了NSDiscardableContent
协议的,就可以把这些对象直接移除。 -
NSDiscardableContent
中有一个计数器count
。当count
>= 1,可以被使用的;当count
== 0, 可以丢弃的。beginContentAccess
会让count
加1,endContentAccess会让count
减1
UIImage *image = [UIImage imageNamed:@"logo"];;
CFDataRef rawData = CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
_testPurgeableData = [[NSPurgeableData alloc] initWithData:(__bridge NSData *)rawData];
[_cache setObject:_testPurgeableData forKey:@"dyz5"];
- (void)dyz_didReceiveMemoryWaring:(NSNotification *)notification{
NSLog(@"notification----%@",notification);
[_testPurgeableData endContentAccess];
}