[官方網站]
Realm.io
[前言]
如果你厭倦了手機使用sqlite資料庫的很多處理方式……
如果你想要一個輕鬆簡單易用的物件封裝式資料庫………
如果你想要有一個讀取效率極佳的資料庫……
如果你希望能夠輕鬆的牽移結構……
如果你想看到一個強大的關連式行動資料庫……
Realm,會是你極佳的選擇。
[支援語言]
swift、Objective-C、Android java、React native、Xamarin C#
[本篇介紹]
語言:Swift 3
資料庫封裝:Realm object
資料庫:Realm
[歷程&介紹]
之前在開發app時,本來想說就使用swift的coredata。可是說真的,coredata要說強大嘛……
是很強大。但是他的寫法封裝說實在的,一點也不優。
在swift 2.0~2.2時,還發生過設定完coredata後,一做結構遷移,整個資料庫的資料就不見了。
還是去看到國外有人在AppDelegate.swift中改了一些code才得以順利的讓遷移後資料不致於不見。
到了swift 3時,我一直在想有沒有人針對sqlite有很好的處理模式或是優化coredata的封裝。
就在那個時候我發現了Realm。
一開始我以為Realm只是另一套sqlite的處理封裝。
直到我在官網好好研究後才發現:他是獨立的資料庫跟資料庫引擎。
在看完官方的介紹,他的操作封裝模式深深吸引了我。
因為他操作的方式實在是簡化到已經非常優的地步了。
處理個資料庫只要少少的幾行code就可以做到非常強大的CRUD。
在其後本來還在為了order by或是group by這一類的東西煩惱著時。
卻發現他有非常強大的RelationShips。
而且更強大的是:可以直接使用關連物件進行CURD行為……
這在往後會慢慢的介紹他。
我沒有很詳細的了解Realm的歷程,貌似是2014年發跡的。
是很新的資料庫。
有人實際測試過他和sqlite的比較。
寫入速度是sqlite的1/2(對!他寫入的速度比sqlite慢了一些。)
讀取速度卻是sqlite的3倍(所以寫入慢或許就是為了優化讀取的關係吧……個人猜測)
[安裝]
官方提供的安裝方式有三種:
1.下載Realm framework,然後匯入到專案 - 麻煩,因為要改一些設定檔。
2.Cocoapods安裝 - 推薦。不用去動設定檔。
3.Carthage - 沒用過。但用過的人是說如果沒使用Cocoapods管理套件的話,可以選用這種方式。
因為我個人都是用Cocoapods來管理套件,所以這邊就只講Cocoapods的安裝。
基本上其實就只要去podfile加上如下的內容:(每個人的pod設定都略有不同,你明白就好)
def shared_pods
pod 'RealmSwift', '~> 2.4.2'
end
target 'your Project' do
shared_pods
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['SWIFT_VERSION'] = ‘3.0’ #如果是swift 2,應該要改成2.3
end
end
end
修改好podfile後再執行pod install即可。
這樣子,就把Realm設定到你的專案了。
[設定資料庫結構]
安裝好之後,你要開始設置你的資料庫結構。
跟coredata的表單設定不同。Realm是直接寫物件封裝來設定結構的。
大致如下:
(我個人有個建議,就是table也就是class的名稱前面都加RLM_,這樣比較不會跟有些類別名稱混淆。)
import UIKit
import RealmSwift
class RLM_User : Object {
private(set) dynamic var uuid:String = UUID().uuidString #這樣的設置就是自動產生uuid
dynamic var name:String = ""
dynamic var age:Int = 0
dynamic var address:String = ""
//設置索引主鍵
override static func primaryKey() -> String {
return "uuid"
}
}
如上面的程式碼,class名稱就是table,屬性名稱就是column。
這邊要注意的是,屬性的型態可以有以下幾種:
Bool, Int, Int8, Int16, Int32, Int64, Double, Float, String, NSDate, NSData
另外第一個的:
private(set) dynamic var uuid:String = UUID().uuidString
意思很簡單:准讀不准寫。
因為他是自動產生uuid,不允許之後去做任何變動。
另外提示一個他跟mysql不同的地方。
Realm基本上取資料是有根據先後順序的。
mysql如果你沒有設定好取資料規則的話。取資料的順序未必是按照你寫入的順序。
也是基於這一點,所以其實你沒有需要設定資料順序的欄位的必要性。
而且在之後他會有很強大的關連物件List來幫你很好的管理「群組」和「資料順序」
(今天先不會介紹關連的強大)
[寫入資料]
當你設定好以上的內容後,接下來就是要寫入資料庫了。
我們在專案中如下編寫code,就可以做到寫入的動作。
import UIKit
import RealmSwift
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.writeData()
}
func writeData() {
let realm = try! Realm()
let user = RLM_User()
user.name = "Sam"
user.age = 40
user.address = "Taipei"
try! realm.write {
realm.add(user)
}
}
}
執行這段程式碼,就可以將資料寫入realm資料庫了。
註:接下來的code我不重複展示整個class,僅以階段的func來展示。
操作練習時請記得自行呼叫func。
[讀取資料]
realm的資取資料真的只能用「簡單到不行」來形容。
可由以下的code看出來。
func readResults(){
let realm = try! Realm()
let users = realm.objects(RLM_User.self) #get users:Type is Results<RLM_User>
if users.count > 0 {
print(users[0].name)
}
}
短短二行,就可以取出user的全部資料放進users。
這邊要注意的是他的資料格式叫做Results<RLM_User>
Results本身是一個陣列,裡面放的是RLM_User的物件。
但他並非是Array()或是NSArray()這一點要稍微注意。
(本篇暫不介紹條件式讀取)
[更新資料]
當你取出資料時,可能需要變動內容再回存。
可參照以下的code來設定更新:
func updateData(){
let realm = try! Realm()
if let user = realm.objects(RLM_User.self).filter("name = 'Sam'").first {
user.age = 20 #年齡詐欺
try! realm.write {
realm.add(user,update:true)
}
}
}
[刪除資料]
最後就是CURD中的刪除了。
其實跟更新的方法類似,只是最後執行的東西不同。
//單一資料刪除
func deleteData(){
let realm = try! Realm()
if let user = realm.objects(RLM_User.self).filter("name = 'Sam'").first {
try! realm.write {
realm.delete(user)
}
}
}
//複合條件刪除
func deleteResults(){
let realm = try! Realm()
let users = realm.objects(RLM_User.self).filter("name = 'Eagle'")
try! realm.write {
realm.delete(users) #砍了老鷹……等一下他要來追殺我了!
}
}
危險:realm其實還有一個方法,叫做deleteAll....顧名思義……使用前請想清楚!
註:要注意的是,realm刪掉資料時並不會刪除檔案的磁區。但他會保留下來供日後其他新增的資料快速寫入。
以上,就是Swift的Realm初探CRUD
等第二篇出來時,會講結構遷移(很重要,卻也很簡單)
[補充]
就在剛剛注意到一個之前沒注意到的update
基本上如果你已經取出資料,是可以直接改資料的。只要寫在realm.write內即可。
func updateData (){
let realm = try! Realm()
if let data = realm.objects(RLM_User.self).filter("name = 'Sam'").first {
try! realm.write {
data.address = "New Taipei City"
}
}
}
realm.add(xxx,update:true)的用法其實是資料不存在是會新增。
而資料存在時會更新。
--
[目次]
[Swift] Realm.io 資料庫介紹 - 其之一:初探CRUD
[Swift] Realm.io 資料庫介紹 - 其之二:Migrations 遷移
[Swift] Realm.io 資料庫介紹 - 其之三:查詢、排序、鍵結、自動更新、筆數