使用 Realm Studio,讓開發更有效率。
您能夠輕鬆地打開任何 Realm 數據庫文件或者 Realm 對象服務器部署對象,並對其進行分析。Realm Studio 容許您輕鬆地打開並編輯本地 Realm 數據庫和可同步 Realm 數據庫,此外還能夠管理 Realm 平臺。可運行在 Mac、Windows 以及 Linux 平臺。ios
下載連接git
github "realm/realm-cocoa"
;carthage update --platform iOS
Carthage/Build/iOS/
中將Realm.framework
、RealmSwift.framework
添加到Xcode 工程的 「General」 設置選項卡的 「Linked Frameworks and Libraries」 部份內;下載地址github
前往 Xcode 工程的 「General」 設置選項卡中,在 ios/、osx/、tvos/ 或者 watchos/ 目錄中選擇適合您項目的 Swift 版本目錄,將 Realm.framework 和 RealmSwift.framework 拖曳到 「Embedded Binaries」 部份內。請確保勾選了 Copy items if needed(除非項目中有多個平臺都須要使用 Realm ),而後單擊 Finish 按鈕; 在單元測試目標的 「Build Settings」 中,將 RealmSwift.framework 的父目錄添加到 「Framework Search Paths」 部分中; 若是在 iOS、watchOS 或者 tvOS 工程中使用 Realm,請在應用目標的 「Build Phases」 中建立一條新的 「Run Script Phase」,而後將下面這段代碼粘貼到腳本文本框內:數據庫
Copy to clipboardbash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework/strip-frameworks.sh" 由於要繞過App Store 出現的提交 bug,所以這一步在打包通用二進制文件時是必須的。swift
在使用Realm中存儲的數據模型都要是Object
類的子類。bash
import Foundation
import RealmSwift
class Dog: Object {
@objc dynamic var id: Int = 0
@objc dynamic var name: String?
}
class Cat: Object {
@objc dynamic var name: String?
}
複製代碼
@objc
是爲了兼容Swift4
服務器
Realm支持的類型:Bool、Int、Int八、Int1六、Int3二、Int6四、Double、Float、String、Date 以及 Data。 其中String、Date 以及 Data 屬性都是可空的,Object 屬性必須可空。app
在上面Dog
中你會發現數值類型是不能寫成Int?
類型的,在Realm中可選數值類型要以下設置:ide
// 可選 int 屬性,默認爲 nil
// RealmOption 屬性應該始終用 `let` 進行聲明,
// 由於直接對其進行賦值並不會起任何做用
let age = RealmOptional<Int>()
複製代碼
let realm = try! Realm()
try! realm.write() {
var person = realm.create(Person.self, value: ["Jane", 27])
// // 讀取或者修改 `RealmOptional` 能夠經過 `value` 屬性實現
person.age.value = 28
}
複製代碼
RealmOptional 支持 Int、Float、Double、Bool,以及全部大小的 Int 版本(包括 Int八、Int1六、Int3二、Int64)。工具
override static func primaryKey() -> String? {
return "id"
}
複製代碼
實現這個方法就能直接設置主鍵
override static func indexedProperties() -> [String] {
return ["title"]
}
複製代碼
實現indexedProperties
進行設置索引屬性。
Realm 支持爲字符串、整型、布爾值以及 Date 屬性創建索引。
類型 | 非可空值形式 | 可空值形式 |
---|---|---|
Bool | @objc dynamic var value = false | let value = RealmOptional() |
Int | @objc dynamic var value = 0 | let value = RealmOptional() |
Float | @objc dynamic var value: Float = 0.0 | let value = RealmOptional() |
Double | @objc dynamic var value: Double = 0. | let value = RealmOptional() |
String | @objc dynamic var value = "" | @objc dynamic var value: String? = nil |
Data | @objc dynamic var value = Data() | @objc dynamic var value: Data? = nil |
Date | @objc dynamic var value = Date() | @objc dynamic var value: Date? = ni |
Object | 不存在:必須是可空值 | @objc dynamic var value: Class? |
List | let value = List() | 不存在:必須是非可空值 |
LinkingObjects | let value = LinkingObjects(fromType: Class.self, property: "property") | 不存在:必須是非可空值 |
//MARK: - 建立數據庫
/// 建立數據庫
///
/// - Parameters:
/// - dataBaseName: 數據庫名字
/// - isReadOnly: 是不是隻讀
/// - Returns: Realm實例
@discardableResult
public func creatDB(_ dataBaseName: String, isReadOnly: Bool = false) -> Realm? {
let realm = openDB(dataBaseName, isReadOnly: isReadOnly)
return realm
}
/// 打開數據庫
///
/// - Parameter name: 數據庫名字
/// - isReadOnly: 是不是隻讀
/// - Returns: Realm實例
@discardableResult
private func openDB(_ dataBaseName: String, isReadOnly: Bool = false) -> Realm? {
guard let dbPath = getCreatDatabasePath(dataBaseName) else {
return nil
}
var config = Realm.Configuration()
config.fileURL = dbPath
config.readOnly = isReadOnly
Realm.Configuration.defaultConfiguration = config
do {
let realm = try Realm.init(configuration: config)
return realm
}catch let error {
mPrint("打開或者建立數據庫失敗:\n\(error.localizedDescription)")
return nil
}
}
複製代碼
在本地生成realm.realm
文件時還會有:
realm.lock
- 資源鎖定文件;realm.management
- 存放進程鎖文件的目錄;realm.note
- 用於通知的命名管道。在報告 Realm 問題的時候,請將這些輔助文件 (auxiliary Realm) 連同主要的 .realm 文件一同提交,由於它們極可能會包含某些對調試問題有用的信息。
打開建立的文件利用RealmStudioda打開會發現,在工程中全部繼承Object
的類直接在Realm中建立了表(暫時未找到具體的緣由)。
/// 打開預植的數據庫
///
/// - Parameters:
/// - dataBaseName: 數據庫名字
/// - isReadOnly: 是不是隻讀
/// - Returns: Realm實例
@discardableResult
public func openReferenceDB(_ dataBaseName: String, isReadOnly: Bool = true) -> Realm? {
guard let dbPath = getReferenceDatabasePaeh(dataBaseName) else {
return nil
}
var config = Realm.Configuration()
config.fileURL = dbPath
config.readOnly = isReadOnly
Realm.Configuration.defaultConfiguration = config
do {
let realm = try Realm.init(configuration: config)
return realm
}catch let error {
mPrint("打開或者建立數據庫失敗:\n\(error.localizedDescription)")
return nil
}
}
複製代碼
defaultConfiguration
/// 設置經過Realm()獲取數據庫的配置
///
/// - Parameters:
/// - realmName: 數據庫的名字
/// - isReadOnly: 是不是這是隻讀
public func setDefaltRealmConfiguration(_ realmName: String,isReference: Bool = false, isReadOnly: Bool = false) -> Bool{
var realmPath: URL?
if isReference {
realmPath = getReferenceDatabasePaeh(realmName)
}else {
realmPath = getCreatDatabasePath(realmName)
}
if realmPath == nil {
return false
}
var config = Realm.Configuration()
config.fileURL = realmPath
config.readOnly = isReadOnly
Realm.Configuration.defaultConfiguration = config
return true
}
複製代碼
/// 獲取當前默認的數據
///
/// - Returns: 返回默認的Realm的數據庫實例
@discardableResult
public func getDefaultRealm() -> Realm? {
do {
return try Realm()
}catch let error {
mPrint("獲取默認的Realm的數據庫失敗:\n\(error.localizedDescription)")
return nil
}
}
複製代碼
若是沒有配置defaultConfiguration
則會獲取默認的數據庫。
/Library/Developer/CoreSimulator/Devices
/26B4D5CC-1EF4-4897-8F02-BCFBE06F7C40/data
/Containers/Data/Application/7CDCBAF4-A7A2-45E4-9B8A-725E873975AD/Documents/default.realm
複製代碼
配置後會獲取到設置路徑的數據庫。
/Library/Developer/CoreSimulator/Devices
/26B4D5CC-1EF4-4897-8F02-BCFBE06F7C40/data
/Containers/Data/Application/E050DEE4-71FB-4866-A10C-CBADA288D35C/Library/Caches/DB/2237DB/2237DB.realm
複製代碼
Realm
的實例不用全局數據共享,在配置默認數據庫後你不管在什麼地方獲取的Realm()
都是同一個數據庫。
//MARK: - 增
/// 建立表 || 更新表
///
/// - Parameters:
/// - type: 表向對應的對象
/// - value: 值
/// - update: 是不是更新, 若是是"true", Realm會查找對象並更新它, 不然添加對象
/// - result: 最後添加對象是成功, 若是成功將對象返回
public func creatObject(_ type: RealmSwift.Object.Type, value: Any? = nil, update: Bool = false, result: ((RealmSwift.Object?, Error?) -> Void)? = nil){
let realm = getDefaultRealm()
do {
try realm?.write {
let object = (value == nil) ? realm?.create(type) : realm?.create(type, value: value!, update: update)
result?(object, nil)
}
} catch let error {
mPrint("獲取默認的Realm的數據庫失敗:\n\(error.localizedDescription)")
result?(nil, error)
}
}
複製代碼
/// 添加數據 || 根據主鍵更新數據
///
/// - Parameters:
/// - object: 要添加的數據
/// - update: 是否更新, 若是是true
/// - result: 添加數據的狀態
public func addObject(_ object: RealmSwift.Object, update: Bool = false, result: ((Error?) -> Void)? = nil) {
let realm = getDefaultRealm()
do {
try realm?.write {
realm?.add(object, update: update)
result?(nil)
}
} catch let error {
mPrint("添加數據失敗:\n \(error.localizedDescription)")
result?(error)
}
}
複製代碼
//MARK: - 刪
/// 刪除數據
///
/// - Parameters:
/// - object: 要刪除的對象
/// - result: 刪除的狀態
public func deleteObject(_ object: RealmSwift.Object, result: ((Error?) -> Void)? = nil) {
let realm = getDefaultRealm()
do {
try realm?.write {
realm?.delete(object)
result?(nil)
}
} catch let error {
mPrint("添加數據失敗:\n \(error.localizedDescription)")
result?(error)
}
}
複製代碼
/// 刪除當前數據庫中全部的數據
///
/// - Parameter result: 刪除的狀態
public func deleteAllObject(result: ((Error?) -> Void)? = nil) {
let realm = getDefaultRealm()
do {
try realm?.write {
realm?.deleteAll()
result?(nil)
}
} catch let error {
mPrint("添加數據失敗:\n \(error.localizedDescription)")
result?(error)
}
}
複製代碼
/// 刪除當前打開的數據庫
///
/// - Parameter dataBaseName: 數據庫的名字
/// - Returns: 刪除的狀態
@discardableResult
public func deleteCreatDBFile() -> Bool {
return autoreleasepool { () -> Bool in
let realmURL = Realm.Configuration.defaultConfiguration.fileURL!
let realmURLs = [
realmURL,
realmURL.appendingPathExtension("lock"),
realmURL.appendingPathExtension("note"),
realmURL.appendingPathExtension("management")
]
for URL in realmURLs {
do {
try FileManager.default.removeItem(at: URL)
return true
} catch {
// 錯誤處理
return false
}
}
return false
}
}
複製代碼
//MARK: - 改
/// 根據主鍵進行更新
///
/// - Parameters:
/// - object: 要更新的對象
/// - update: 是否根據主鍵更新, 若是是"false"則是添加數據
/// - result: 更新數據的結果
public func updateObject(_ object: RealmSwift.Object, update: Bool = true, result: ((Error?) -> Void)? = nil) {
addObject(object, update: update, result: result)
}
複製代碼
/// 根據主鍵進行更新
///
/// - Parameters:
/// - type: 要更新的對象類型
/// - value: 要更新的值, 例如: ["id": 1, "price": 9000.0]
/// - update: 是否根據主鍵進行更新, 若是爲"false"則爲建立表
/// - result: 更新的結果
public func updateObject(_ type: RealmSwift.Object.Type, value: Any? = nil, update: Bool = true, result: ((RealmSwift.Object?, Error?) -> Void)? = nil) {
creatObject(type, value: value, update: update, result: result)
}
複製代碼
/// 直接更新對象
///
/// - Parameters:
/// - property: 要更改的屬性
/// - value: 更改的值
/// - Returns: 更改的結果
@discardableResult
public func updateObject( property: inout Any, value: Any) -> Bool {
let realm = getDefaultRealm()
do {
try realm?.write {
property = value
}
return true
} catch let error {
mPrint("直接更新對象屬性錯誤: \(error.localizedDescription)")
return false
}
}
複製代碼
/// 更改表中全部的字段的值
///
/// - Parameters:
/// - type: 表的對象類型
/// - key: 要更改的字段名
/// - value: 更改的值
/// - Returns: 返回更改結果
public func updateObjects(type: RealmSwift.Object.Type, key: String, value: Any) -> Bool {
let objects = getObjects(type: type)
do {
try getDefaultRealm()?.write {
objects?.setValue(value, forKeyPath: key)
}
return true
} catch let error {
mPrint("更改一個表中的全部數據錯誤: \(error.localizedDescription)")
return false
}
}
複製代碼
/// 根據主鍵進行對某個對象中的數據進行更新
///
/// - Parameters:
/// - type: 表類型
/// - primaryKey: 主鍵
/// - key: 要更改屬性
/// - value: 更改的值
/// - Returns: 更改的狀態
public func updateObject(type: RealmSwift.Object.Type, primaryKey: Any, key: String, value: Any) -> Bool {
let object = getObjectWithPrimaryKey(type: type, primaryKey: primaryKey)
do {
try getDefaultRealm()?.write {
object?.setValue(value, forKeyPath: key)
}
return true
} catch let error {
mPrint("更新數據出錯: \(error.localizedDescription)")
return false
}
}
複製代碼
//MARK: - 查
/// 查找一個表中的全部的數據
///
/// - Parameter type: 對象類型
/// - Returns: 查到的數據
public func getObjects(type: RealmSwift.Object.Type) -> RealmSwift.Results<RealmSwift.Object>?{
return getDefaultRealm()?.objects(type)
}
複製代碼
/// 根據主鍵查找某個對象
///
/// - Parameters:
/// - type: 對象類型
/// - primaryKey: 主鍵
/// - Returns: 查到的數據
public func getObjectWithPrimaryKey(type: RealmSwift.Object.Type, primaryKey: Any) -> RealmSwift.Object? {
return getDefaultRealm()?.object(ofType: type, forPrimaryKey: primaryKey)
}
複製代碼
/// 使用斷言字符串查詢
///
/// - Parameters:
/// - type: 對象類型
/// - filter: 過濾條件
/// - Returns: 查詢到的數據
/// - example:
/// - var tanDogs = realm.objects(Dog.self).filter("color = 'tan' AND name BEGINSWITH 'B'")
public func getObject(type: RealmSwift.Object.Type, filter: String) -> RealmSwift.Results<RealmSwift.Object>? {
return getObjects(type: type)?.filter(filter)
}
複製代碼
/// 使用謂詞進行查詢
///
/// - Parameters:
/// - type: 對象類型
/// - predicate: 謂詞對象
/// - Returns: 查詢到的數據
/// - example:
/// - let predicate = NSPredicate(format: "color = %@ AND name BEGINSWITH %@", "tan", "B")
/// - tanDogs = realm.objects(Dog.self).filter(predicate)
public func getObject(type: RealmSwift.Object.Type, predicate: NSPredicate) -> RealmSwift.Results<RealmSwift.Object>? {
return getObjects(type: type)?.filter(predicate)
}
複製代碼
/// 對查詢的數據進行排序,請注意, 不支持 將多個屬性用做排序基準,此外也沒法鏈式排序(只有最後一個 sorted 調用會被使用)。 若是要對多個屬性進行排序,請使用 sorted(by:) 方法,而後向其中輸入多個 SortDescriptor 對象。
///
/// - Parameters:
/// - type: 對象類型
/// - filter: 過濾條件
/// - sortedKey: 須要排序的字段
/// - Returns: 最後的結果
public func getObject(type: RealmSwift.Object.Type, filter: String, sortedKey: String) -> RealmSwift.Results<RealmSwift.Object>? {
return getObject(type: type, filter: filter)?.sorted(byKeyPath: sortedKey)
}
複製代碼
/// 對查詢的數據進行排序, 請注意, 不支持 將多個屬性用做排序基準,此外也沒法鏈式排序(只有最後一個 sorted 調用會被使用)。 若是要對多個屬性進行排序,請使用 sorted(by:) 方法,而後向其中輸入多個 SortDescriptor 對象。
///
/// - Parameters:
/// - type: 隊形類型
/// - predicate: 謂詞對象
/// - sortedKey: 排序的字段
/// - Returns: 排序後的數據
public func getObject(type: RealmSwift.Object.Type, predicate: NSPredicate, sortedKey: String) -> RealmSwift.Results<RealmSwift.Object>? {
return getObject(type: type, predicate: predicate)?.sorted(byKeyPath: sortedKey)
}
複製代碼
Realm 擁有許多可以表示一組對象的類型,稱之爲 「Realm 集合」:
Realm 集合類型均實現了 RealmCollection 協議,這確保 它們的行爲均保持一致。這個協議繼承自 CollectionType,所以它的使用方式 與標準庫內的集合相同。這個協議也一樣聲明瞭其餘經常使用的 Realm 集合 API, 好比說檢索、排序、聚合操做等等。List 還存在一些額外的修改操做, 這些操做沒有在協議接口中定義,好比說添加或者刪除對象。
使用 RealmCollection 協議, 您能夠編寫可以對任意 Realm 集合進行操做的泛型代碼:
Copy to clipboardfunc operateOn<C: RealmCollection>(collection: C) {
// collection 既能夠是 RLMResults,也能夠是 RLMArray
print("operating on collection containing \(collection.count) objects")
}
複製代碼
因爲 Swift 類型系統的限制,必須使用諸如 AnyRealmCollection 之類的無類型封裝器,才能將這個集合存儲在屬性或者變量中:
Copy to clipboardclass ViewController {
// let collection: RealmCollection
// ^
// error: protocol 'RealmCollection' can only be used
// as a generic constraint because it has Self or
// associated type requirements
//
// init<C: RealmCollection>(collection: C) where C.ElementType == MyModel {
// self.collection = collection
// }
let collection: AnyRealmCollection<MyModel>
init<C: RealmCollection>(collection: C) where C.ElementType == MyModel {
self.collection = AnyRealmCollection(collection)
}
}
複製代碼
Realm的基礎使用先寫到這裏,更詳細的能夠直接看文檔(真的很詳細)。
在使用RealmSwift增刪改查又用RxSwift封裝了一層。
項目地址
謝謝