📱 iOS數據持久化
? 核心概念
數據持久化是指將內存中的數據以特定格式保存到持久存儲介質(如硬盤)的過程,使得應用重啟后數據依然可用。在iOS中,由于沙盒機制的限制,應用只能訪問自己沙盒內的文件。
沙盒目錄是每個iOS應用獨有的文件系統空間,與其他應用隔離,保證了數據的安全性。主要目錄包括:
- Documents: 存放用戶數據,iTunes同步時會備份。
- Library/Caches: 存放緩存數據, iTunes同步時不會備份。適合存儲體積較大、不需要備份的非重要數據,如網絡緩存。
- Library/Preferences: 存放偏好設置文件(通常通過NSUserDefaults操作),iTunes同步時會備份。
- tmp: 存放臨時文件,系統可能在應用未運行時清除此目錄,iTunes同步時不會備份。
🔍 主要持久化方案對比
方案 | 適用場景 | 特點 | 注意事項 |
---|---|---|---|
屬性列表 (Plist) | 存儲少量結構化數據(如配置信息) | 支持NSArray, NSDictionary等類型,XML格式,易讀寫 | 不能存儲自定義對象,數據量大了性能差 |
偏好設置 (NSUserDefaults) | 用戶偏好設置(如音量、開關狀態) | 鍵值對存儲,使用簡單,數據自動保存到plist文件 | 不要存儲敏感數據,非即時寫入(必要時調用synchronize ) |
歸檔 (NSKeyedArchiver) | 存儲自定義對象 | 可將對象序列化為二進制數據,支持加密,安全性較好 | 需對象實現NSCoding 或NSSecureCoding 協議 |
SQLite & FMDB | 大量結構化數據,需要復雜查詢 | SQLite輕量級,FMDB是它的OC封裝,面向對象,多線程安全 | 需編寫SQL語句(FMDB可簡化),處理數據庫升級邏輯 |
Core Data | 復雜數據模型,對象圖管理 | ORM框架,管理對象生命周期,支持數據遷移、撤銷重做 | 學習曲線較陡峭,需理解其堆棧(Context, Coordinator, Model) |
💡 如何選擇持久化方案
選擇哪種方案,就像為不同的物品挑選不同的收納工具,需要根據你的數據特點和業務需求來決定:
- 小量簡單配置或用戶設置:如是否首次啟動、用戶名等,用 NSUserDefaults。
- 少量結構化數據:如城市列表、銀行名稱等不常修改的數據,可用 Plist。
- 自定義對象:如用戶信息、游戲存檔,需實現
NSCoding
協議,使用歸檔。 - 大量有規律的數據,需頻繁增刪改查:如聊天記錄、新聞列表,用數據庫(SQLite/FMDB或Core Data)。
- 若追求更輕量級和直接控制SQL,選FMDB。
- 若需管理復雜對象關系、希望與系統深度集成,選Core Data。
- 敏感信息:如用戶密碼、令牌,使用Keychain(鑰匙串),它是系統級加密存儲,應用刪除后數據仍可保留。
🎯 常見面試問題與回答思路
-
iOS中主要有哪幾種數據持久化方案?
- 思路:列出上述5種核心方案,并簡要說明每種最適用的場景,展示你全面的了解。
-
NSUserDefaults 和 Keychain 有什么區別?
- 思路:NSUserDefaults用于存儲非敏感的普通偏好設置,存儲在沙盒的plist文件中。Keychain用于存儲敏感信息,如密碼、證書,提供加密保護,存儲于系統級別,應用刪除后數據仍存在(常用于存用戶唯一標識)。
-
Core Data 和 SQLite 有什么區別?
- 思路:Core Data是一個對象圖管理和持久化框架,并非數據庫。它可將對象保存到SQLite、XML等多種存儲中。它提供高級功能如數據遷移、關系管理、撤銷重做。SQLite是一個輕量級的關系型數據庫,通過SQL操作數據。Core Data在底層可以使用SQLite作為存儲后端。
-
如何保證 Core Data 的多線程安全?
- 思路:強調私有隊列上下文(Private Queue Context)的重要性。告知每個線程應使用獨立的NSManagedObjectContext,并通過NSManagedObjectID在不同線程間傳遞對象引用。核心是避免多個線程共享同一個Context或ManagedObject。
-
什么是歸檔?如何實現一個自定義對象的歸檔?
- 思路:歸檔是一種對象序列化機制,可將對象及其屬性關系轉換為二進制數據流(NSData)進行存儲或傳輸。
- 實現步驟:
- 讓自定義類遵守
NSCoding
或NSSecureCoding
協議。 - 實現協議中的兩個方法:
encode(with:)
: 在此方法中將對象的每個屬性進行編碼(encodeObject(_:forKey:)
等)。init(coder:)
: 在此方法中解碼(decodeObject(forKey:)
等)并初始化對象的每個屬性。
- 使用
NSKeyedArchiver
的archiveRootObject(_:toFile:)
方法歸檔。 - 使用
NSKeyedUnarchiver
的unarchiveObject(withFile:)
方法解檔。
- 讓自定義類遵守
-
沙盒中各個目錄的作用是什么?應用上架時需要注意什么?
- 思路:清晰說明Documents、Caches、Preferences、tmp目錄的區別(如上文所述)。特別要注意,如果把緩存文件或臨時文件放在Documents目錄,可能會導致應用上架審核被拒,因為iTunes會同步備份Documents目錄,而蘋果要求此目錄僅存儲用戶產生的重要數據。
🚀 面試進階提示
- 結合項目經驗:當被問到持久化時,最好能結合你項目中的實際使用場景。例如:“在我的上一個項目中,我使用Core Data來管理用戶的收藏列表,因為它能很好地處理對象之間的關系和變化跟蹤。”
- 了解底層原理:如果你能簡要說明FMDB如何封裝SQLite的C API,或Core Data的堆棧結構(Persistent Store Coordinator, Managed Object Model, Managed Object Context),會大大加分。
- 提及性能優化:對于數據庫操作,可以提及通過事務(Transaction) 來批量處理數據插入或更新,顯著提升性能。
- 強調安全性:如果談到敏感信息存儲,一定要主動提到Keychain,這體現了你的安全意識。