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