NSCache

作者: Code_人生 | 来源:发表于2019-09-30 13:58 被阅读0次
  • 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];
}

相关文章

网友评论

      本文标题:NSCache

      本文链接:https://www.haomeiwen.com/subject/fcrdyctx.html