使用 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封装了一层。
项目地址
谢谢