一、FMDB簡單介紹
FMDB是OC的方式封裝了SQLite的C語言API,並且它對於多執行緒的併發操作進行了處理,所以是執行緒安全的;相對系統提供的CoreData,輕量好多,使用起來也很方便,除查詢以外的所有操作,都稱為“更新”,這裡就不詳細介紹了,不是本文的主題
二、為什麼要再封裝?
- 1、隔離網路第三方框架,方便修改維護
- 2、雖然FMDB已經封裝了SQLite,但依然需要寫SQL語句,對於模型中屬性比較多的話,拼接SQL語句將變得十分繁瑣;而且對於字串、字典、陣列資料是沒辦法直接存入資料庫,需要特殊處理。
因此封裝面向模型,只需要傳入對應的模型資訊就能進行資料庫操作,不需要寫任何SQL語句,遮蔽內部所有操作,插入什麼模型,就取出什麼模型,簡單易用!同時為了保證傳入的都是模型資料,新增了異常提示,對傳入的模型做了限制,必須是NSObject或者NSObject的子類,同時不響應事件
- 3、FMDB中操作執行異常只會列印出來(例如沒有對應表的時候的操作),如果專案中列印資訊比較多的話,不容易察覺。
因此操作異常時新增斷言,準確定位操作異常位置以及異常情況
- 4、對資料庫操作後需要關閉資料庫,此時增加了程式碼量,而且容易忘記,記憶體沒辦法及時釋放。
因此將關閉資料庫操作封裝在框架中,此時呼叫不需要關心資料庫的關閉
- 5、面向模型開發,操作模型,更加物件導向,以前一般用資料庫的時候一般都是直接儲存後臺返回的資料,此時每次取出來都要轉一次模型,麻煩
三、API介紹(增刪改查)
單例模式,專案中唯一,方便管理,但也只能建立一個資料庫
1 2 3 4 5 6 |
<span class="hljs-comment">/** * <span class="hljs-doctag">@author</span> Clarence * * 單例建立,專案唯一 */</span> + (instancetype)shareManager; |
創表,外界傳入指定的類,工具會根據類來建立表,如果此時表已經存在,則跳過,沒有才去建立,執行完這個操作後自動關閉資料庫,釋放記憶體
1 2 3 4 5 6 7 8 |
#<span class="hljs-operator"><span class="hljs-keyword">pragma</span> mark <span class="hljs-comment">-- 創表</span> <span class="hljs-comment">/** * @author Clarence * * 根據類名建立表,如果有則跳過,沒有才建立,執行完畢後自動關閉資料庫 */</span> - (BOOL)fl_createTable:(<span class="hljs-keyword">Class</span>)modelClass;</span> |
插入資料,可以傳入單個模型,或者傳入模型陣列,此時內部處理了,遍歷陣列插入的期間資料庫不會關閉,直到所有插入完畢後才關閉資料庫;同時,如果傳入的模型的FLDBID在對應表中已經存在,則執行更新操作,保證FLDBID對應資料的唯一性
1 2 3 4 5 6 7 8 9 10 11 12 |
#<span class="hljs-operator"><span class="hljs-keyword">pragma</span> mark <span class="hljs-comment">-- 插入</span> <span class="hljs-comment">/** * @author Clarence * * @param model 插入單個模型或者模型陣列,如果此時傳入的模型對應的FLDBID在表中已經存在,則替換更新舊的 * 如果沒建立表就自動先建立,表名為模型類名 * 此時執行完畢後自動關閉資料庫 * @return YES or NO */</span> - (BOOL)fl_insertModel:(<span class="hljs-keyword">id</span>)<span class="hljs-keyword">model</span>;</span> |
查詢 提供三個方法
- 查詢表是否存在,執行完畢就會自動關閉資料庫,由於此方法存在,框架工具中會出現錯誤提示資訊,因為如果沒有對應表,執行操作語句FMDB就會列印出錯誤資訊
- 查詢指定表中指定FLDBID的單個模型資料,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言
- 查詢指定表中模型陣列(所有的),執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="hljs-id">#pragma</span> <span class="hljs-tag">mark</span> <span class="hljs-tag">--</span> 查詢 <span class="hljs-comment">/** * @author Clarence * * 查詢指定表是否存在,執行完畢後自動關閉資料庫 */</span> <span class="hljs-tag">-</span> (<span class="hljs-tag">BOOL</span>)<span class="hljs-rule"><span class="hljs-attribute">fl_isExitTable</span>:<span class="hljs-value">(Class)modelClass</span></span>; <span class="hljs-comment">/** * @author Clarence * * 查詢指定表中指定FLDBID的模型,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言 */</span> <span class="hljs-tag">-</span> (<span class="hljs-tag">id</span>)<span class="hljs-rule"><span class="hljs-attribute">fl_searchModel</span>:<span class="hljs-value">(Class)modelClass byID:(NSString *)FLDBID</span></span>; <span class="hljs-comment">/** * @author Clarence * * 查詢指定表中模型陣列(所有的),執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言 */</span> <span class="hljs-tag">-</span> (<span class="hljs-tag">NSArray</span> *)<span class="hljs-rule"><span class="hljs-attribute">fl_searchModelArr</span>:<span class="hljs-value">(Class)modelClass</span></span>; |
修改 根據指定FLDBID,將新傳入的模型替換舊的模型資料,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言
1 2 3 4 5 6 7 8 9 |
#<span class="hljs-operator"><span class="hljs-keyword">pragma</span> mark <span class="hljs-comment">-- 修改</span> <span class="hljs-comment">/** * @author Clarence * * 修改指定DBID的模型,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言 */</span> - (BOOL)fl_modifyModel:(<span class="hljs-keyword">id</span>)<span class="hljs-keyword">model</span> byID:(NSString *)FLDBID;</span> |
刪除,此時也提供了三個方法
- 刪除指定表,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言
- 刪除指定表格的所有資料,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言
- 刪除指定表中指定FLDBID的模型,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="hljs-id">#pragma</span> <span class="hljs-tag">mark</span> <span class="hljs-tag">--</span> 刪除 <span class="hljs-comment">/** * @author Clarence * * 刪除指定表,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言 */</span> <span class="hljs-tag">-</span> (<span class="hljs-tag">BOOL</span>)<span class="hljs-rule"><span class="hljs-attribute">fl_dropTable</span>:<span class="hljs-value">(Class)modelClass</span></span>; <span class="hljs-comment">/** * @author Clarence * * 刪除指定表格的所有資料,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言 */</span> <span class="hljs-tag">-</span> (<span class="hljs-tag">BOOL</span>)<span class="hljs-rule"><span class="hljs-attribute">fl_deleteAllModel</span>:<span class="hljs-value">(Class)modelClass</span></span>; <span class="hljs-comment">/** * @author Clarence * * 刪除指定表中指定FLDBID的模型,執行完畢後自動關閉資料庫,如果沒有對應表,會有斷言 */</span> <span class="hljs-tag">-</span> (<span class="hljs-tag">BOOL</span>)<span class="hljs-rule"><span class="hljs-attribute">fl_deleteModel</span>:<span class="hljs-value">(Class)modelClass byId:(NSString *)FLDBID</span></span>; |
四、呼叫以及效果圖(只舉部分例子,詳細請移步gitHub,有完整的Demo介紹)
增
1 |
<span class="hljs-list">[<span class="hljs-keyword">FLFMDBMANAGER</span> fl_insertModel:arrM]<span class="hljs-comment">;</span></span> |
刪
1 |
[FLFMDBMANAGER fl_deleteModel:[FLStudentModel class] byId:model.FLDBID] |
改
1 |
[[FLFMDBManager shareManager] fl_modifyModel:model byID:model.FLDBID] |
查
1 |
[FLFMDBMANAGER fl_searchModel:[FLStudentModel class] byID:textField.text] |
五、使用注意點以及不足之處
- 單例模式,因此只能建立一個資料庫,對於聊天賬號的資料儲存就可能不適用
- 內部暫時使用FMDatabase這個類,執行緒不安全的,如果在多個執行緒中同時使用一個FMDatabase例項,會造成資料混亂等問題,後續會新增FMDatabaseQueue處理,執行緒安全
-
需要在模型中新增一個屬性FLDBID,NSString型別,為了繫結對應的資料,從而進行增刪改查操作
- 需要插入資料庫的模型不支援繼承,因為根據類名來建立表,框架內部只能讀取當前類的屬性,其父類的屬性沒辦法獲取
- 修改資料庫中的模型資料只能通過指定的FLDBID作為條件修改
- 暫時不支援模型屬性動態刪減,如果刪了對應屬性(除了FLDBID)不影響使用,但如果增加屬性了,只能從新建表儲存
- 巢狀模型暫時不支援單表處理,需要建立多張表處理
- 為了保證操作安全,框架工具中新增判斷表是否存在,因此如果表不存在,此時執行判斷就會出現一個操作error提示,不影響使用
12<span class="hljs-strong">** DB Error: 1 "no such table: 對應表名"**</span><span class="hljs-strong">** DB Query: SELECT * FROM 對應表名**</span>
六、小總結
- 技術上實現並沒多難,使用runtime就很容易獲取當前模型類中的屬性,關鍵還是處理一系列邏輯,程式碼比較簡單,這裡就不詳細講解了,Demo中有相對應的註釋 !
- 每個人都有自己的程式設計想法和愛好,有人喜歡面向字典開發、有人喜歡面向模型開發,我就喜歡面向模型封裝,遮蔽內部處理邏輯,呼叫只需要一句程式碼,享受封裝的過程~
- 最後,還是那句,如果你有什麼問題或者建議,儘管留言,歡迎大家關注我,喜歡就給個like 和 star,隨時更新!謝謝支援!
-
gitHub地址,歡迎star