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之后沙盒路径都不一样,这是系统为保证数据安全,都会复制新的一份数据到新路径,所以不会有问题。

问题

  1. 真机运行失败

参考,这里有一个坑,选择 Embed Without Signing之后,真机运行时会出现无法运行的情况。改成 Embed & Signed 即可。

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

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

iOS中的MMKV是一个高性能、轻量级的键值存储库,可以用于持久化数据。它由微信团队开发,通过使用C++编写的底层存储引擎,提供了比NSUserDefaults更快速和可靠的存储解决方案。 要在iOS使用MMKV进行持久化,你可以按照以下步骤进行操作: 1. 集成MMKV库:首先,需要将MMKV库添加到你的iOS项目中。你可以通过CocoaPods或手动导入方式添加依赖。具体的集成步骤可以参考MMKV的官方文档。 2. 创建MMKV实例:在使用MMKV之前,你需要创建一个MMKV实例来操作数据。可以使用下面的代码创建一个MMKV实例: ``` // 导入MMKV头文件 #import <MMKV/MMKV.h> // 创建MMKV实例 NSString *mmkvID = @"your_mmkv_id"; MMKV *mmkv = [MMKV mmkvWithID:mmkvID]; ``` 在创建MMKV实例时,需要指定一个唯一的ID来区分不同的实例。这个ID会被用作数据存储的文件名。 3. 存储数据:使用MMKV实例可以方便地存储各种类型的数据。例如,存储字符串可以使用以下代码: ``` NSString *key = @"your_key"; NSString *value = @"your_value"; [mmkv setString:value forKey:key]; ``` 除了字符串外,MMKV还支持存储其他基本数据类型(如整数、布尔值等),以及NSData对象。 4. 读取数据:使用MMKV实例可以快速读取存储的数据。以下是一个读取字符串数据的示例: ``` NSString *key = @"your_key"; NSString *value = [mmkv getStringForKey:key]; ``` 同样地,你也可以使用适当的方法来读取其他类型的数据。 通过这些简单的步骤,你可以在iOS应用中使用MMKV库进行持久化操作。希望这能对你有所帮助!如果有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值