1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import
Foundation
import
RealmSwift
//消費類型
class
ConsumeType
:
Object
{
//類型名
@objc
dynamic
var
name =
""
}
//消費條目
class
ConsumeItem
:
Object
{
//條目名
@objc
dynamic
var
name =
""
//金額
@objc
dynamic
var
cost = 0.00
//時間
@objc
dynamic
var
date =
Date
()
//所屬消費類別
@objc
dynamic
var
type:
ConsumeType
?
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
import
UIKit
import
RealmSwift
class
ViewController
:
UIViewController
{
override
func
viewDidLoad() {
super
.viewDidLoad()
//使用默認的數據庫
let
realm = try!
Realm
()
//查詢所有的消費記錄
let
items = realm.objects(
ConsumeItem
.
self
)
//已經有記錄的話就不插入了
if
items.count>0 {
return
}
//創建兩個消費類型
let
type1 =
ConsumeType
()
type1.name =
"購物"
let
type2 =
ConsumeType
()
type2.name =
"娛樂"
//創建三個消費記錄
let
item1 =
ConsumeItem
(value: [
"買一臺電腦"
,5999.00,
Date
(),type1])
//可使用數組創建
let
item2 =
ConsumeItem
()
item2.name =
"看一場電影"
item2.cost = 30.00
item2.date =
Date
(timeIntervalSinceNow: -36000)
item2.type = type2
let
item3 =
ConsumeItem
()
item3.name =
"買一包泡麪"
item3.cost = 2.50
item3.date =
Date
(timeIntervalSinceNow: -72000)
item3.type = type1
// 數據持久化操作(類型記錄也會自動添加的)
try! realm.write {
realm.add(item1)
realm.add(item2)
realm.add(item3)
}
//打印出數據庫地址
print
(realm.configuration.fileURL ??
""
)
}
override
func
didReceiveMemoryWarning() {
super
.didReceiveMemoryWarning()
}
}
|
1
2
|
//打印出數據庫地址
print
(realm.configuration.fileURL ??
""
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
import
UIKit
import
RealmSwift
class
ViewController
:
UIViewController
,
UITableViewDelegate
,
UITableViewDataSource
{
@IBOutlet
weak
var
tableView:
UITableView
!
var
dformatter =
DateFormatter
()
//保存從數據庫中查詢出來的結果集
var
consumeItems:
Results
<
ConsumeItem
>?
override
func
viewDidLoad() {
super
.viewDidLoad()
self
.dformatter.dateFormat =
"MM月dd日 HH:mm"
self
.tableView!.delegate =
self
self
.tableView!.dataSource =
self
//創建一個重用的單元格
self
.tableView!.register(
UITableViewCell
.
self
, forCellReuseIdentifier:
"MyCell"
)
//使用默認的數據庫
let
realm = try!
Realm
()
//查詢所有的消費記錄
consumeItems = realm.objects(
ConsumeItem
.
self
)
}
//在本例中,只有一個分區
func
numberOfSections(
in
tableView:
UITableView
) ->
Int
{
return
1;
}
//返回表格行數(也就是返回控件數)
func
tableView(_ tableView:
UITableView
, numberOfRowsInSection section:
Int
) ->
Int
{
return
self
.consumeItems!.count
}
//創建各單元顯示內容(創建參數indexPath指定的單元)
func
tableView(_ tableView:
UITableView
, cellForRowAt indexPath:
IndexPath
)
->
UITableViewCell
{
//同一形式的單元格重複使用,在聲明時已註冊
let
cell =
UITableViewCell
(style: .value1, reuseIdentifier:
"MyCell"
)
let
item =
self
.consumeItems![indexPath.row]
cell.textLabel?.text = item.name +
" ¥"
+
String
(format:
"%.1f"
, item.cost)
cell.detailTextLabel?.text =
self
.dformatter.string(from: item.date)
return
cell
}
override
func
didReceiveMemoryWarning() {
super
.didReceiveMemoryWarning()
}
}
|
1
2
3
4
5
6
|
//查詢並取出前5條數據
let
dogs = try!
Realm
().objects(
Dog
.
self
)
for
i
in
0..<5 {
let
dog = dogs[i]
// ...
}
|
1
2
3
4
5
6
7
8
9
|
//查詢花費超過10元的消費記錄(使用斷言字符串查詢)
consumeItems = realm.objects(
ConsumeItem
.
self
).
filter
(
"cost > 10"
)
//查詢花費超過10元的購物記錄(使用 NSPredicate 查詢)
let
predicate =
NSPredicate
(format:
"type.name = '購物' AND cost > 10"
)
consumeItems = realm.objects(
ConsumeItem
.
self
).
filter
(predicate)
//使用鏈式查詢
consumeItems = realm.objects(
ConsumeItem
.
self
).
filter
(
"cost > 10"
).
filter
(
"type.name = '購物'"
)
|
1
2
|
//查詢花費超過10元的消費記錄,並按升序排列
consumeItems = realm.objects(
ConsumeItem
.
self
).
filter
(
"cost > 10"
).sorted(byKeyPath:
"cost"
)
|
1
2
3
4
5
6
7
8
9
10
|
class
Person
:
Object
{
...
// 其餘的屬性聲明
let
dogs =
List
<
Dog
>()
}
// 這裏我們就可以使用已存在的狗狗對象來完成初始化
let
aPerson =
Person
(value: [
"李四"
, 30, [aDog, anotherDog]])
// 還可以使用多重嵌套
let
aPerson =
Person
(value: [
"李四"
, 30, [[
"小黑"
, 5], [
"旺財"
, 6]]])
|
1
2
3
|
let
someDogs = realm.objects(
Dog
.
self
).
filter
(
"name contains '小白'"
)
ZhangSan
.dogs.append(objectsIn: someDogs)
ZhangSan
.dogs.append(dahuang)
|
1
2
3
4
5
6
7
8
|
class
Dog
:
Object
{
@objc
dynamic
var
name =
""
@objc
dynamic
var
age = 0
// Realm 並不會存儲這個屬性,因爲這個屬性只定義了 getter
// 定義「owners」,和 Person.dogs 建立反向關係
let
owners =
LinkingObjects
(fromType:
Person
.
self
, property:
"dogs"
)
}
|
1
2
3
4
5
6
7
8
|
class
Person
:
Object
{
@objc
dynamic
var
id = 0
@objc
dynamic
var
name =
""
override
static
func
primaryKey() ->
String
? {
return
"id"
}
}
|
1
2
3
4
5
6
7
8
|
class
Book
:
Object
{
@objc
dynamic
var
price = 0
@objc
dynamic
var
title =
""
override
static
func
indexedProperties() -> [
String
] {
return
[
"title"
]
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
class
Person
:
Object
{
@objc
dynamic
var
tmpID = 0
var
name:
String
{
// 計算屬性將被自動忽略
return
"\(firstName) \(lastName)"
}
@objc
dynamic
var
firstName =
""
@objc
dynamic
var
lastName =
""
override
static
func
ignoredProperties() -> [
String
] {
return
[
"tmpID"
]
}
}
|
1
2
3
4
|
// 在一個事務中更新對象
try! realm.write {
consumeItem.name =
"去北京旅行"
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/****** 方式1 ***/
// 創建一個帶有主鍵的「書籍」對象,作爲事先存儲的書籍
let
cheeseBook =
Book
()
cheeseBook.title =
"奶酪食譜"
cheeseBook.price = 9000
cheeseBook.id = 1
// 通過 id = 1 更新該書籍
try! realm.write {
realm.add(cheeseBook, update:
true
)
}
/****** 方式2 ***/
// 假設帶有主鍵值 `1` 的「書籍」對象已經存在
try! realm.write {
realm.create(
Book
.
self
, value: [
"id"
: 1,
"price"
: 22], update:
true
)
// 這本書的`title`屬性不會被改變
}
|
1
2
3
4
5
6
7
|
let
persons = realm.objects(
Person
.
self
)
try! realm.write {
// 更新第一個
persons.first?.setValue(
true
, forKeyPath:
"isFirst"
)
// 將每個人的 planet 屬性設置爲「地球」
persons.setValue(
"地球"
, forKeyPath:
"planet"
)
}
|
1
2
3
4
5
6
|
let
cheeseBook = ...
// 存儲在 Realm 中的 Book 對象
// 在事務中刪除一個對象
try! realm.write {
realm.delete(cheeseBook)
}
|
1
2
3
4
|
// 從 Realm 中刪除所有數據
try! realm.write {
realm.deleteAll()
}
|
1
2
3
4
5
6
7
8
9
10
|
func
setDefaultRealmForUser(username:
String
) {
var
config =
Realm
.
Configuration
()
// 使用默認的目錄,但是使用用戶名來替換默認的文件名
config.fileURL = config.fileURL!.deletingLastPathComponent()
.appendingPathComponent(
"\(username).realm"
)
// 將這個配置應用到默認的 Realm 數據庫當中
Realm
.
Configuration
.defaultConfiguration = config
}
|
1
2
3
4
5
6
7
8
9
10
11
|
let
config =
Realm
.
Configuration
(
// 獲取需要打包文件的 URL 路徑
fileURL:
Bundle
.main.url(forResource:
"MyBundledData"
, withExtension:
"realm"
),
// 以只讀模式打開文件,因爲應用數據包並不可寫
readOnly:
true
)
// 通過配置打開 Realm 數據庫
let
realm = try!
Realm
(configuration: config)
// 通過配置打開 Realm 數據庫
let
results = realm.objects(
Dog
.
self
).
filter
(
"age > 5"
)
|
1
|
let
realm = try!
Realm
(configuration:
Realm
.
Configuration
(inMemoryIdentifier:
"MyInMemoryRealm"
))
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/***** 在創建 Realm 數據庫時採用64位的密鑰對數據庫文件進行 AES-256+SHA2 加密 ****/
// 產生隨機密鑰
var
key =
Data
(count: 64)
_ = key.withUnsafeMutableBytes { bytes
in
SecRandomCopyBytes
(kSecRandomDefault, 64, bytes)
}
// 打開加密文件
let
config =
Realm
.
Configuration
(encryptionKey: key)
let
realm:
Realm
do {
realm = try
Realm
(configuration: config)
} catch
let
error
as
NSError
{
// 如果密鑰錯誤,`error` 會提示數據庫不可訪問
fatalError(
"Error opening realm: \(error)"
)
}
// 和往常一樣使用 Realm 即可
let
dogs = realm.objects(
Book
.
self
).
filter
(
"name contains 'Fido'"
)
|
1
2
3
4
5
|
class
Person
:
Object
{
@objc
dynamic
var
firstName =
""
@objc
dynamic
var
lastName =
""
@objc
dynamic
var
age = 0
}
|
1
2
3
4
|
class
Person
:
Object
{
@objc
dynamic
var
fullName =
""
@objc
dynamic
var
age = 0
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// 在(application:didFinishLaunchingWithOptions:)中進行配置
let
config =
Realm
.
Configuration
(
// 設置新的架構版本。這個版本號必須高於之前所用的版本號
// (如果您之前從未設置過架構版本,那麼這個版本號設置爲 0)
schemaVersion: 1,
// 設置閉包,這個閉包將會在打開低於上面所設置版本號的 Realm 數據庫的時候被自動調用
migrationBlock: { migration, oldSchemaVersion
in
// 目前我們還未進行數據遷移,因此 oldSchemaVersion == 0
if
(oldSchemaVersion < 1) {
// 什麼都不要做!Realm 會自行檢測新增和需要移除的屬性,然後自動更新硬盤上的數據庫架構
}
})
// 告訴 Realm 爲默認的 Realm 數據庫使用這個新的配置對象
Realm
.
Configuration
.defaultConfiguration = config
// 現在我們已經告訴了 Realm 如何處理架構的變化,打開文件之後將會自動執行遷移
let
realm = try!
Realm
()
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// 在 application(application:didFinishLaunchingWithOptions:) 中進行配置
Realm
.
Configuration
.defaultConfiguration =
Realm
.
Configuration
(
schemaVersion: 1,
migrationBlock: { migration, oldSchemaVersion
in
if
(oldSchemaVersion < 1) {
// enumerateObjects(ofType:_:) 方法遍歷了存儲在 Realm 文件中的每一個「Person」對象
migration.enumerateObjects(ofType:
Person
.className()) { oldObject, newObject
in
// 將名字進行合併,存放在 fullName 域中
let
firstName = oldObject![
"firstName"
]
as
!
String
let
lastName = oldObject![
"lastName"
]
as
!
String
newObject![
"fullName"
] =
"\(firstName) \(lastName)"
}
}
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|