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小同學
個人網站

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