[官方网站]
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'endtarget 'your Project' do shared_podsendpost_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 endend
修改好podfile后再执行pod install即可。
这样子,就把Realm设定到你的专案了。
[设定资料库结构]
安装好之后,你要开始设置你的资料库结构。
跟coredata的表单设定不同。Realm是直接写物件封装来设定结构的。
大致如下:
(我个人有个建议,就是table也就是class的名称前面都加RLM_,这样比较不会跟有些类别名称混淆。)
import UIKitimport RealmSwiftclass 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 UIKitimport RealmSwiftclass 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 资料库介绍 - 其之三:查询、排序、键结、自动更新、笔数