Skip to content

iOS_advance_cn

guoling edited this page Sep 2, 2020 · 5 revisions

MMKV for iOS/macOS

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

iOS/macOS 进阶

MMKV 有一些高级设置,可以使得更符合你的需求。

日志

  • MMKV 默认将日志打印到 console,对线上问题的解决很不便。你可以在 App 启动时接收转发 MMKV 的日志。实现MMKVHandler协议,添加类似下面的代码:

    - (void)mmkvLogWithLevel:(MMKVLogLevel)level file:(const char *)file line:(int)line func:(const char *)funcname message:(NSString *)message {
        const char *levelDesc = nullptr;
        switch (level) {
            case MMKVLogDebug:
                levelDesc = "D";
                break;
                case MMKVLogInfo:
                levelDesc = "I";
                break;
            case MMKVLogWarning:
                levelDesc = "W";
                break;
            case MMKVLogError:
                levelDesc = "E";
                break;
            default:
                levelDesc = "N";
                break;
        }
        // use your own logging tool
        //NSLog(@"[%s] <%s:%d::%s> %@", levelDesc, file, line, funcname, message);
    }

    至于使用哪个客户端日志组件,我们推荐使用 xlog,同样也是开源自微信团队。

  • 如果你不希望 MMKV 打印日志,你可以在 MMKV 初始化时一劳永逸地关掉它(虽然我们强烈不建议你这么做)。

    [MMKV initializeMMKV:nil logLevel:MMKVLogNone];

数据恢复

  • 在 crc 校验失败,或者文件长度不对的时候,MMKV 默认会丢弃所有数据。你可以让 MMKV 恢复数据。要注意的是修复率无法保证,而且可能修复出奇怪的 key-value。同样地也是实现MMKVHandler协议,添加以下代码:

    - (MMKVRecoverStrategic)onMMKVCRCCheckFail:(NSString *)mmapID {
        return MMKVOnErrorRecover;
    }
    
    - (MMKVRecoverStrategic)onMMKVFileLengthError:(NSString *)mmapID {
        return MMKVOnErrorRecover;
    }

自定义根目录

  • MMKV 默认把文件存放在$(Documents)/mmkv/目录。你可以在 MMKV 初始化时自定义根目录:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    auto libraryPath = (NSString *) [paths firstObject];
    auto rootDir = [libraryPath stringByAppendingPathComponent:@"mmkv_2"];
    [MMKV initializeMMKV:rootDir];
  • MMKV 甚至支持自定义某个文件的目录:

    auto path = [MMKV mmkvBasePath];
    path = [path stringByDeletingLastPathComponent];
    path = [path stringByAppendingPathComponent:@"mmkv_3"];
    auto mmkv = [MMKV mmkvWithID:@"test/case1" relativePath:path];

加密

  • MMKV 默认明文存储所有 key-value,依赖 iOS/macOS 系统的沙盒机制保证文件加密。如果你担心信息泄露,你可以选择加密 MMKV。

    NSData *cryptKey = [@"My-Encrypt-Key" dataUsingEncoding:NSUTF8StringEncoding];
    auto mmkv = [MMKV mmkvWithID:@"MyID" cryptKey:cryptKey];
  • 你可以更改密钥,也可以将一个加密 MMKV 改成明文,或者反过来。

    NSString *mmapID = @"testAES_reKey";
    // an unencrypted MMKV instance
    MMKV *kv = [MMKV mmkvWithID:mmapID cryptKey:nullptr];
    
    NSData *key_1 = [@"Key_seq_1" dataUsingEncoding:NSUTF8StringEncoding];
    // change from unencrypted to encrypted
    [kv reKey:key_1];
    
    NSData *key_2 = [@"Key_seq_2" dataUsingEncoding:NSUTF8StringEncoding];
    // change encryption key
    [kv reKey:key_2];
    
    // change from encrypted to unencrypted
    [kv reKey:nullptr];

自动清理

  • MMKV 默认缓存所有访问过的 MMKV 实例, 并在收到 memory warning 的时候清理他们的内部缓存。不过 MMKV 不会彻底销毁他们,除非手工调用 -[MMKV close]。你可以在 MMKV 初始化后调用 +[MMKV enableAutoCleanUp:] 开启 自动清理逻辑:

    // auto clean up instances that not been accessed in 10 minutes
    [MMKV enableAutoCleanUp:10];

下一步

Clone this wiki locally