YMCache 2.2.0

YMCache 2.2.0

测试已测试
编程语言语言 Obj-CObjective C
许可证 MIT
发布上次发布2021年12月

Maintained by Adam Kaplan, David Grandinetti, David Grandinetti.



YMCache 2.2.0

  • 作者:
  • adamkaplan

YMCache

build-status

Swift Package Manager compatible CocoaPods Compatible GitHub license Supported Platforms


YMCache 是一个轻量级对象缓存解决方案,适用于 iOS 和 macOS,专为高度并行的访问场景设计。YMCache 通过模拟 NSMutableDictionary 提供一个熟悉的应用程序接口,同时在内部利用 Apple 的 Grand Central Dispatch 技术来实现性能和一致性的平衡。

YahooFinance iOS 团队使用 YMCache 来多路复用对其成千上万的实时股票数据的访问,这些股票以不可预测的方式变化,变化速度也不可预测。YMCache 通过提供一系列易于理解的 读/写锁 访问语义,帮助减轻对中央数据存储的线程访问复杂性。

并行访问

  1. 所有读操作总是在调用线程上同步执行,但在所有读者间并发执行(在系统资源允许的情况下)。
  2. 所有写操作会异步执行
  3. 在写操作之后引发的读操作将等待写操作完成

上述规则允许有多个读者和一个写者。这种方法的美好结果是,读操作与写操作是串行的,强制执行一个合理的顺序:您可以确信预期的数据已完整写入。

功能

  • 持久性:将缓存保存/加载到磁盘一次,或在定义的间隔内
  • 淘汰策略:处理低内存情况,使用符合你需求的任何逻辑
  • 序列化:任意模型转换免费。您可以使用 Mantle、直接的 NSJSONSerialization 或任何其他您能想到的格式!
  • 批量操作:高效的多值读写。 (批量操作遵循 并行访问规则,但算作单个操作)

配置

我们支持通过 CocoaPodsSwift 包管理器 进行分发。

CocoaPods

  1. 将 YMCache 添加到项目的 Podfile

    target :MyApp do
      pod 'YMCache', '~> 1.0'
    end
  2. 在项目目录中运行 pod updatepod install

SwiftPM

.package(url: "https://github.com/yahoo/YMCache.git", from: "2.2.0") 添加到您的 package.swift

使用

摘要

YMMemoryCache *cache = [YMMemoryCache memoryCacheWithName:@"my-object-cache"];
cache[@"Key1"] = valueA;
MyVal *valueA = cache[@"Key1"];
[cache addEntriesFromDictionary:@{ @"Key2": value2 }];
NSDictionary *allItems = [cache allItems];
[cache removeAllObjects];
// cache = empty; allItems = @{ @"Key1": value1, @"Key2": value2 }

此缓存本质上是一个完全线程安全的 NSDictionary,具有读写顺序保证。

驱逐

手动驱逐
// Create memory cache with an eviction decider block, which will be triggered for each item in the cache whenever
// you call `-purgeEvictableItems:`.
YMMemoryCache *cache = [YMMemoryCache memoryCacheWithName:@"my-object-cache"
                                          evictionDecider:^(NSString *key, NewsStory *value, void *context) {
                                              return value.publishDate > [NSDate dateWithTimeIntervalSinceNow:-300];
                                          }];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [cache purgeEvictableItems:nil];
    });

此示例缓存包括一个驱逐块,该块在10秒延迟后被调用一次。您负责实现决策逻辑以确定哪些条目可以安全地被驱逐。在这种情况下,超过5分钟未发布的NewsStory模型将从缓存中清除。在这种情况下,驱逐决策将在主队列上调用,因为这是从哪里调用-purgeEvictableItems:的地方。

基于时间的驱逐
YMMemoryCache *cache = [YMMemoryCache memoryCacheWithName:@"my-object-cache"
                                          evictionDecider:^(NSString *key, NewsStory *value, void *context) {
                                              return value.publishDate > [NSDate dateWithTimeIntervalSinceNow:-300];
                                          }];

cache.evictionInterval = 60.0; // trigger eviction every 60 seconds

这将在每60秒创建一个具有基于时间的缓存驱逐的缓存。请注意,驱逐决策者的自动调用将在一个任意背景线程上执行。此方法可以与其他手动驱逐调用相结合,以提供一种情况,其中缓存驱逐是按需触发的,但至少每隔N分钟。

低内存状态下的自动驱逐
// Create memory cache with an eviction decider block, which will be triggered for each item in the cache whenever
// you call `-purgeEvictableItems:`.
YMMemoryCache *cache = [YMMemoryCache memoryCacheWithName:@"my-object-cache"
                                          evictionDecider:^(NSString *key, NewsStory *value, void *context) {
                                              return value.publishDate > [NSDate dateWithTimeIntervalSinceNow:-300];
                                          }];

// Trigger in-band cache eviction during low memory events.
[[NSNotificationCenter defaultCenter] addObserver:cache
                                         selector:@selector(purgeEvictableItems:)
                                             name:UIApplicationDidReceiveMemoryWarningNotification
                                           object:nil];

// or, more commonly

- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning];

    // Trigger immediate synchronous cache cleanup
    [self.cache purgeEvictableItems:nil];
}

响应低内存情况的驱逐决策块将在主线程上执行,因为只有主线程会发送低内存通知或调用-didReceiveMemoryWarning

观察变化

YMMemoryCache *cache = [YMMemoryCache memoryCacheWithName:@"my-object-cache"];

cache.notificationInterval = 0.5;

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(cacheUpdated:)
                                             name:kYFCacheDidChangeNotification
                                           object:cache];

// from any thread, such as a network client on a background thread
cache[@"Key"] = value;

// within 0.5s (as per configuration) a notification will fire and call this:
- (void)cacheUpdated:(NSNotification *)notification {
    // Get a snapshot of all values that were added or replaced since the last notification
    NSDictionary *addedOrUpdated = notification.userInfo[kYFCacheUpdatedItemsUserInfoKey];
    // Get a set of all keys that were removed since the last notification
    NSSet *removedKeys = notification.userInfo[kYFCacheRemovedItemsUserInfoKey];
}

文件加密(iOS)和写入选项

YMCachePersistenceManager 使用 NSData 读取和写入磁盘上的数据。默认情况下,我们会以原子方式写入。您可以通过设置持久管理器的 fileWritingOptions 属性来控制写入选项,在下一个写入之前。

示例

要运行示例项目,请克隆存储库,然后从 Example 目录中的某个目录运行 pod install

示例:Mantle 序列化

使用 Mantle(版本 1 或 2)将缓存序列化为磁盘非常简单!查看 Examples/Mantle 中的预构建、现成的示例。

支持和贡献

报告任何错误或发送功能请求到 GitHub 问题。欢迎贡献拉取请求。有关详细信息,请参阅 CONTRIBUTING

许可证

MIT 许可证。有关详细信息,请参阅 LICENSE 文件。