數據庫?
現在重新來思考數據庫的封裝問題,首先就需要弄清楚FMDB數據庫的原理和基本邏輯,首先弄清楚FMDB其實是一個封裝的方法庫,因為iOS中原生的SQLite API在使用上相當不友好,在使用時,非常不便。于是,就出現了一系列將SQLite API進行封裝的庫,例如FMDB、PlausibleDatabase、sqlitepersistentobjects等,FMDB是一款簡潔、易用的封裝庫。通過FMDB來管理SQLite,需要添加libsqlite3.0.dylib這個框架。FMDB有三個主要的類1.FMDatabase – 表示一個單獨的SQLite數據庫。 用來執行SQLite的命令。2.FMResultSet – 表示FMDatabase執行查詢后結果集 3.FMDatabaseQueue – 如果你想在多線程中執行多個查詢或更新,你應該使用該類。這是線程安全的
使用數據庫的第一件事,就是在特定的路徑下建立一個數據庫。但是要注意的是,iOS環境下只有document directory 是可以進行讀寫的。而Resource資料夾底下的東西都是read-only。因此,建立的數據庫必須放在document 資料夾下。創建FMDatabase對象時,參數為SQLite數據庫的文件路徑。該路徑可以是以下三種之一:1.文件路徑。該文件路徑無需真實存,如果不存在會自動創建。2..空字符串(@”")。表示會在臨時目錄創建一個空的數據庫,當FMDatabase 鏈接關閉時,文件也被刪除。3.NULL. 將創建一個內在數據庫。同樣的,當FMDatabase連接關閉時,數據會被銷毀。
[FMDatabase databaseWithPath:]
如果是新建的數據庫,一開始里面是沒有類似于Excel表格的。建立Excel表格的方式很簡單。但在和數據庫交互時,數據庫必須是打開狀態。執行更新后都會返回一個BOOL值。YES表示執行成功,否則就表示出現錯誤 。通過調用 lastErrorMessage或lastErrorCode方法可以得到更多信息。
那么又回歸到了最本質的問題,為什么總是感覺我不會使用這個FMDB第三方庫來操作原生的SQLite數據呢?我是用的太少還是說有什么關鍵的地方沒有學到,可是是哪一點沒有學好呢?看來的仔細排查。首先我知道FMDB是一個對原生SQLite數據庫進行操作而封裝的庫。那么作為一個數據庫來說,肯定就是為了存儲東西數據嘛!而且通常情況下存儲的都是表格也就是類似于Excel的這種表格。可是如何才能把這種表格的數據進行方便的操作就是FMDB的意義所在。你可能會問,既然里面是以類似于鍵值對的形式存儲起來,那么為什么不考慮用可變字典來存儲數據呢?對呀?為什么不適用可變字典呢?問題就是字典里的鍵值對根本不具備數據庫的“增刪改查”的靈活性,而且你還會發現一個區別就是字典里的鍵不能相同,也就是不能夠存在重復數據的情況。也就是說:一個鍵只能對應一個值,但是數據庫就不一樣了。數據庫的一個鍵可以對應很多個值!而且最關鍵最關鍵的就是,數據里的數據是可以全工程共享的。而存在可變字典里的鍵值對,根本很不方便在全工程里使用!
還有對于一個表格來說首先就是要創建吧?當然工程里的表格是不能直接被創建的,因為這樣就跟字典沒有什么兩樣了!根本無法使得這個存儲數據的表格在全工程里被調用了!所以必須將這個看似字典其實更類似于Excel的表格放到一個數據庫里,而且必須把數據庫放到一個固定的路徑里。這樣整個工程都可以根據這個數據庫的固定路徑找到數據庫順而找到這個更類似于Excel的表格。從而就能夠對表格里的數據鍵值對進行編輯了!
好了,現在嘗試一下通過FMDB如何創建數據庫又如何編輯數據庫里面的表格里的鍵值對。首先給這個類輸入一個路徑參數固定通過FMDB的初始化方式實例化一個的SQLite數據庫對象。這里的NSHomeDirectory()就是app應用的根地址!然后必須放在根地址的可讀可寫的Documents文件夾里,同時設置好這個數據庫的名字叫做data.db。
[[FMDatabase alloc]initWithPath:[NSString stringWithFormat:@"%@/Documents/data.db",NSHomeDirectory()]];
接著判斷已經實例化的對象的打開數據庫方法是否為真,如果為真,就在這個數據庫里面執行對象的創建表格的方法。create創造一個表格,名字叫XXX,然后傳入一個數組,像是一個字典中包含所有鍵的數組。
[對象 executeUpdate:@"create table 表名(鍵1,鍵2,鍵3)”]
現在表格已經創建完成,就可以往表格里面添加東西進行編輯了,編輯就是增刪改查!首先就是往表格里面添加內容,也就是鍵值對的形式。使用insert插入到表格中所有鍵的值,更像是一個字典中的值的數組呀!
[對象 executeUpdate:@"insert into 表名 values(值1,值2,值3)”]
現在就是刪除表格中滿足特定條件的鍵值對,delete從表格中,判斷的條件就是根據值來進行分類,只要一個鍵的值是條件里的限定值,就進行刪除操作!
[對象 executeUpdate:@"delete from 表名 where 鍵1 = ? or 鍵2 = ? or 鍵3 = ?”,限定值,限定值,限定值]
所謂的替換依然使用where來進行條件判斷,如果只要滿足where里的某一類鍵的值的條件,就通過set來重新對這類鍵的值進行設置。
[對象 executeUpdate:@"update 表名 set 鍵 = ? where 值 > 30(范圍)",替補內容]
最后就是通過FMResultSet創建一個集合來接收通過select來接收的表格里所有的鍵值對。但由于這個result是一個集合,所以不能使用遍歷,因為集合類似于鏈表,頭結點是空的,而且是沒有順序的。因此通過While同時結合[result next]的方法在While的循環里每次都判斷[result next]的值是否為空,這樣就可以實現對集合的鍵值對逐行進行判斷。同時在while循環的遍歷時,通過創建字符串對象或其它data數據來接收集合里每一行的所有鍵所對應的值。同時因為數據庫里面的表格里只能存儲string類型和data類型的鍵值對。所以通常接收也用相應地類型。要么NSString,要么NSData。而且這里學到一個新東西就是創建一個數據模型的新型方式,先總結一下過去創建一個有值的字典的集中方式,肯定無一例外首先都是先實例化一個對象,要么在實例化對象的時候就直接給字典里添加鍵值對,要么在實例化字典對象之后,在以set方式來進行添加一個鍵值對,或者以set的方式同時添加鍵數組和值數組。現在再總結一下過去只要一面臨很多鍵值對時,如果想要提取出鍵值對里面鍵所對應的值,首先想到的方法就是建立一個數據模型,至于為什么要建立一個數據模型好型并沒有描述。要知道數據庫的表格里面其實的每一行都相當于三個鍵值對并排而存在。所以在通過while和[result next]結合使用遍歷集合中的每一行時,每一次都相當于遍歷一個字典里的所有鍵值對。話說到這兒,其實思路也很清晰了,就是其實數據庫的表格更像是一個包含許多個相類似字典的數組,這才是數據庫的表格的本質。那么在遍歷表格里的每一行時就非常類似于遍歷一個數組中的每一個字典。那么如何才能在不用數據模型的情況下接收并存儲原本存儲在表格的每一行的鍵值對呢?其實就是將原本設置在模型.h文件中的模型對象的屬性現在直接在while的遍歷里進行初始化的同時并將數據庫的表格里的每一行的鍵值對的鍵對應的值賦值初始化的字符串對象或Data對象。然后將初始化的所有對象名組合成一個數組對象添加到可變數組中。比較model數據模型,這個while遍歷里本該使用[model setValueWithDictionary:Dict]KVC方法來對數據模型model對象的所有屬性進行賦值。然后是將model對象添加到可變數組中,而不使用數據模型時雖然將原本寫在數據模型.h文件里的屬性全部移到了while的遍歷循環里,而且相當于在初始化屬性的同時就將字典鍵對應的值賦值給屬性。那么將這些在While遍歷里創建的屬性組合成一個數組對象然后添加到可變數組中和那種將數據模型對象添加到可變數組中,在使用時有什么不一樣么?當然答案肯定是不一樣的,因為可變數組中添加的是數據模型對象時想要獲取值是通過點語法來實現,而當可變數組中添加的是裝了屬性名的數組對象時想要獲取值必須通過數組加下標號來實現!不知你有沒有發現,其實這就是Model數據模型誕生的本質!
1、NSHomeDirectory()就是 App Home。包含App bundle的目錄,不要在該路徑下寫任何文件。
/Documents/。使用該路徑放置關鍵數據,也就是不能通過App重新生成的數據。該路徑可通過配置實現iTunes共享文件。可被iTunes備份。(現在保存在該路徑下的文件還需要考慮iCloud同步)
/Library/。該路徑下一般保存著用戶配置文件。可創建子文件夾。可以用來放置您希望被備份但不希望被用戶看到的數據。該路徑下的文件夾,除Caches以外,都會被iTunes備份。
/tmp/。使用該路徑保存臨時文件。App應該刪除那些不再被使用的文件,系統也會在App關閉后刪除殘留文件。該路徑下的文件不會被iTunes備份。
5.數據源追加后重載數據顯示在tableView上,只要對數據庫編輯后都需要重載數據,使用完數據庫需要關閉數據庫,如何提高效率呢?數據庫做成一個單例,在應用啟動的時候,就打開數據庫,當進入后臺就關閉數據庫。
[fm beginTransaction];
[fm rollback];//發現錯誤全部撤銷刪除
[fm commit];// 如果沒有錯誤,則進行提交