iOS-MMKV的使用

简介

github地址

MMKV 是基于 mmap 内存映射的 key-value 组件,底层序列化/反序列化使用 protobuf 实现,性能高,稳定性强。从 2015 年中至今在微信上使用,其性能和稳定性经过了时间的验证。近期也已移植到 Android / macOS / Win32 / POSIX 平台,一并开源。

源起

在微信客户端的日常运营中,时不时就会爆发特殊文字引起系统的 crash,参考文章,文章里面设计的技术方案是在关键代码前后进行计数器的加减,通过检查计数器的异常,来发现引起闪退的异常文字。在会话列表、会话界面等有大量 cell 的地方,希望新加的计时器不会影响滑动性能;另外这些计数器还要永久存储下来——因为闪退随时可能发生。这就需要一个性能非常高的通用 key-value 存储组件,我们考察了 SharedPreferences、NSUserDefaults、SQLite 等常见组件,发现都没能满足如此苛刻的性能要求。考虑到这个防 crash 方案最主要的诉求还是实时写入,而 mmap 内存映射文件刚好满足这种需求,我们尝试通过它来实现一套 key-value 组件。

原理

  • 内存准备

通过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由操作系统负责将内存回写到文件,不必担心 crash 导致数据丢失。

  • 数据组织

数据序列化方面我们选用 protobuf 协议,pb 在性能和空间占用上都有不错的表现。

  • 写入优化

考虑到主要使用场景是频繁地进行写入更新,我们需要有增量更新的能力。我们考虑将增量 kv 对象序列化后,append 到内存末尾。

  • 空间增长

使用 append 实现增量更新带来了一个新的问题,就是不断 append 的话,文件大小会增长得不可控。我们需要在性能和空间上做个折中。

更详细的介绍MMKV原理

分析mmap

iOS接入指南

  • 通过CocoaPods安装
    1.编辑 Podfile 文件,添加 pod 'MMKV'
    2.命令行输入 pod install
    3.然后添加头文件 #import <MMKV/MMKV.h> 即可使用。

还有 Carthage安装,通过动态库、静态库安装的方式。更多接入方式:参考

  • 此处增加一种以Framework方式添加的方式
    1.下载源码
    2.Cmd+B 编译

在 Xcode11 之后,模拟器默认只支持x86_64架构,因此编译出的framework使用时会出现缺失 i386架构的问题。

首先,添加 i386架构
MMKV

core

然后,下载老版本的 Simulator。
iOS 10.3.1

最后,选择模拟器(如:iphone 11 支持x86_64,iphone 5 支持i386),Cmd+B 编译。
Products --> 右键show in finder
framework

对于 .a 和 .framework,分别查询其支持的架构:

lipo -info 路径/libMMKVCore.a
lipo -info 路径/MMKV.framework/MMKV

合并i386和x86_64架构到x86_64:
lipo -create x86_64路径/libMMKVCore.a i386路径/libMMKVCore.a -output x86_64路径/libMMKVCore.a

lipo -create x86_64路径/MMKV.framework/MMKV i386路径/MMKV.framework/MMKV -output x86_64路径/MMKV.framework/MMKV

3.将合并后的framework,直接添加到项目中,会出现以下问题。
dyld: Library not loaded: @rpath/MMKV.framework/MMKV Referenced from: /Users/nazimai/Library/Developer/CoreSimulator/Devices/F89E46FD-39DA-4D0B-B0E9-F441B3B944B7/data/Containers/Bundle/Application/A8BA7019-C057-4186-A533-CDB20019B110/Test.app/Test Reason: image not found
error

将framework修改成如下:
Embed

再次运行,即可正常使用。

“Do Not Embed”、“Embed & Sign”、“Embed Without Signing” 区别?
参考

Embed,嵌入,对于静态库选择Do Not Embed,动态链接选择Embed。
Sign,签名,如果代码没有签名则选择Embed & Sign,否则Embed Without Signing。

简单了解库的区别:
iOS 静态库,动态库与 Framework

Xcode11之后,苹果推出 XCFramework 替代Framework。有兴趣可以自行搜索查看。

简单使用

  • 启动时初始化以及简单使用
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    [MMKV initializeMMKV:nil];
    
    [[MMKV defaultMMKV] setString:@"123" forKey:@"wq"];
    
    NSString *str = [[MMKV defaultMMKV] getStringForKey:@"wq"];
    
    NSLog(@"MMKV----->%@", str);
    
    return YES;
}

初始化时参数为nil,MMKV会默认创建沙盒路径。
当然也可以自己创建沙盒路径,通过打印发现每次打开App之后沙盒路径都不一样,这是系统为保证数据安全,都会复制新的一份数据到新路径,所以不会有问题。

=================================================================
个人博客
Github
个人公众号:Flutter小同学
Flutter小同学
个人网站

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章