Realm入门

来源:互联网 发布:金石工程计价软件 编辑:程序博客网 时间:2024/06/05 04:41

官网,在官网上查看文档教程。为查看数据可安装Realm Browser

内容来自raywenderlich

Realm入门

这里使用的是Realm并不是最新的版本,Cocoapod如下:

platform :ios, ‘9.0’use_frameworks!target 'Todoify' do  pod 'RealmSwift', '~> 0.98'end

通过简单的继承 Object 或者一个已经存在的模型类,您就可以创建一个新的 Realm 数据模型对象

属性的类型
属性类型

绝大多数的属性都需要一个前缀dynamic,让Realm把属性与底层的C++映射起来

主键(Primary Keys):重写 Object.primaryKey() 可以设置模型的主键。声明主键之后,对象将允许进行查询,并且更新速度更加高效,而这也会要求每个对象保持唯一性。 一旦带有主键的对象被添加到 Realm 之后,该对象的主键将不可修改。

  override class func primaryKey() -> String? {    return "id"  }

索引属性(Indexed Properties):重写 Object.indexedProperties() 方法可以为数据模型中需要添加索引的属性建立索引。对属性进行索引可以减少插入操作的性能耗费,加快比较检索的速度(比如说 = 以及 IN 操作符)

  override class func indexedProperties() -> [String] {    return ["title"]  }

忽略属性(Ignored Properties):重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性。

  override class func ignoredProperties() -> [String] {    return ["tmpID"]  }

基本用法

以实现一个待办事项的app为例,使用realm来保存待办的事项,所以先创建一个Task类,Task类继承自Object

Task任务类

import Foundationimport RealmSwiftclass Task: Object {    dynamic var taskId = NSUUID().UUIDString    dynamic var title = ""    dynamic var done = false    dynamic var created = NSDate()    dynamic var priority = 0    convenience init(title: String, priority: Int) {        self.init()        self.title = title        self.priority = priority    }    override class func primaryKey() -> String? {        return "taskId"    }    override class func indexedProperties() -> [String] {        return ["done"]    }}extension Task {    var priorityText: String {        return priority > 0 ? "High" : "Default"    }    var priorityColor: UIColor {        return priority > 0 ? UIColor.redColor() : UIColor.blueColor()    }}

Realm不会尝试初始化任何没有setter的属性 - 包括任何只读和动态属性。
extension中的priorityText属性没有setter方法,所以Realm不会试图将其在disc上或内存中保存下来


在保存或者查询数据之前,要获取Realm的一个引用,最简单的方式是获取默认的Realm的实例,获取的应用的默认的realm,位于沙盒的Documents文件夹中

let realm = try! Realm()

沙盒

如果想让Realm在app的另外的位置,可指定location的URL。或者你做更多的配置,可创建Realm.Configuration

let realm = try! Realm(fileURL: myUrl)let myConfig = Realm.Configuration(fileURL: myUrl)let realm = try! Realm(configuration: myConfig)

保存

例如,保存一个待办事项Task

    let realm = try! Realm()    let task = Task(title: taskTitle.text!, priority: taskPrio.selectedSegmentIndex)    // 通过事务将数据添加到 Realm 中    try! realm.write({        realm.add(task)    })

查询

查询操作,Realm将会返回包含Object集合的Results实例。
Results的特点

  • Results are typed例如获取类型为Dog的数据或者获取类型为Person的数据
  • the data is dynamic (zero copy)表示Realm不会从disc复制任何数据到memory,总是直接从disc获取数据,所以获取的总是最新的数据。从disc读取数据并会不会占用内存
  • queryable and sortable可查询,可排序
  • NSPredicate相似的语法

例如,查询所有的Task
先定义一个变量来保存tasks,类型为Results<Task>

var tasks: Results<Task>!

查询所有Task

    let realm = try! Realm()    tasks = realm.objects(Task)

更新

Realm 提供了一系列用以更新数据的方式,这些方式都有着各自所适应的情景

内容直接更新

在写入事务中通过设置某个对象的属性从而完成对象的更新操作

// 在一个事务中更新对象try! realm.write {  author.name = "托马斯·品钦"}

通过主键更新

如果您的数据模型中设置了主键的话,那么您可以使用Realm().add(_:update:)来更新对象,或者当对象不存在时插入新的对象。

// 创建一个带有主键的“书籍”对象,作为事先存储的书籍let cheeseBook = Book()cheeseBook.title = "奶酪食谱"cheeseBook.price = 9000cheeseBook.id = 1// 通过 id = 1 更新该书籍try! realm.write {  realm.add(cheeseBook, update: true)}

如果主键 id 为1的 Book 对象已经存在于数据库当中了,那么对象就会简单地进行更新。而如果不在数据库中存在的话,那么这个操作将会创建一个新的 Book 对象并添加到数据库当中。

您同时通过传递您想要更新值的集合,从而更新带有主键的某个对象的部分值,比如说如下所示:

// 假设带有主键值 `1` 的“书籍”对象已经存在try! realm.write {  realm.create(Book.self, value: ["id": 1, "price": 9000.0], update: true)// 这本书的`title`属性不会被改变}

教程的这个例子是先通过taskId主键获取到task,然后通过内容直接更新, 如下:

    if let realm = try? Realm(),        let id = taskId,        let task = realm.objectForPrimaryKey(Task.self, key: id){        try! realm.write({             task.done = checked        })        check.selected = task.done    }

删除

通过在写入事务中将要删除的对象传递给 Realm().delete(_:) 方法

// 在事务中删除一个对象try! realm.write {  realm.delete(cheeseBook)}

删除所有数据

// 从 Realm 中删除所有数据try! realm.write {  realm.deleteAll()}

教程中的这个例子,删除待办事项,滑动cell删除

        try! tasks.realm!.write({            let task = tasks[indexPath.row]            self.tasks.realm?.delete(task)        })

集合

在前面的例子中,获取到了全部的数据。但在大部分应用的场合,我们需要的并不是全部的数据,而是符合某些条件的特定数据,这就要用到过滤filter,对数据和可以应用sorter进行排序

这里写图片描述


本例中,使用filter来过滤出done == true的数据,并且按照prioritycreated排序
请注意,sorted(byKeyPath:) 以及 sorted(byProperty:) 不支持将多个属性用作排序基准,如果要按多个属性进行排序的话,请使用 sorted(by:) 方法,然后向其中传递多个 SortDescriptor 对象。

func getTask(done: Bool) -> Results<Task>{    let realm = try! Realm()    tasks = realm.objects(Task)    if done {        tasks = tasks.filter("done == true")    }    //return tasks.sorted("created", ascending: false)    return tasks.sorted([                SortDescriptor(property: "priority", ascending: false),                SortDescriptor(property: "created", ascending: false)        ])}

Realm 集合

  • Results类,表示从检索 中所返回的对象集合。
  • List类,表示模型中的对多关系。
  • LinkingObjects类,表示模型中的反向关系。

本例中,添加一个User类,一个user可对应多个task,如下:

class User: Object {    dynamic var name = ""    //User对应的tasks    let tasks = List<Task>()    convenience init(name: String) {        self.init()        self.name = name    }}

那么,在保存Task的时候,可直接使用如下的形式:

    let realm = try! Realm()    let task = Task(title: taskTitle.text!, priority: taskPrio.selectedSegmentIndex)    let user = users[taskUsers.selectedSegmentIndex]    try! realm.write({        user.tasks.append(task)    })

如上user.tasks.append(task),这样做数据不会重复

Realm 通知

Realm 支持对象级别的通知。您可以在特定的 Realm 对象上进行通知的注册,这样就可以在此对象被删除时、或者该对象所管理的属性值被修改时(同样也适用于当对象所管理的属性值被设置为既有值的时候),获取相应的通知。

对象级别的通知

changes有三种值:

  • .Initial(collection)
  • .Update(collection, deletes,inserts, updates)
  • .Error(error)

本例,在tasks上注册通知,使用的方式,官方文档中有详细的介绍

var subscription: NotificationToken?func notificationSubscription(tasks: Results<Task>) -> NotificationToken {    return tasks.addNotificationBlock({ [weak self] (change: RealmCollectionChange<Results<Task>>) in        self?.updateUI(change)        })}func updateUI(change: RealmCollectionChange<Results<Task>>) {    switch change {    case .Initial(_):        tableView.reloadData()    case .Update(_, let deletions, let insertions, _):        tableView.beginUpdates()        tableView.insertRowsAtIndexPaths(insertions.map({NSIndexPath(forRow: $0, inSection: 0)}), withRowAnimation: .Automatic)        tableView.deleteRowsAtIndexPaths(deletions.map({NSIndexPath(forRow: $0, inSection: 0)}), withRowAnimation: .Automatic)        tableView.endUpdates()        break    case .Error(let error):        print(error)    }}

其它文章

  • Realm数据库 从入门到“放弃”
  • iOS中Realm数据库的基本用法
0 0
原创粉丝点击