测试已测试 | ✓ |
语言语言 | SwiftSwift |
许可证 | MIT |
发布上次发布 | 2016年6月 |
SPM支持 SPM | ✗ |
由 Pol Quintana 维护。
Swift 编写的用于 Realm 的 NSFetchedResultsController 实现
RealmRequest<T>
需要三个参数
其中 T
是一个 Realm
模型
let realm = // Your realm DB
let predicate = NSPredicate(format: "id != 0")
let sortDescriptors = [SortDescriptor(property: "projectID"), SortDescriptor(property: "name")]
let request = RealmRequest<TaskModel>(predicate: predicate, realm: realm, sortDescriptors: sortDescriptors)
RealmResultsController<T, U>
需要 4 个参数
RealmRequest<T>
func mapper(obj: T) -> U
(可选)func filter(obj: T) -> Bool
(可选)其中 T
是一个 Realm
模型,U
是您想要从 RRC 收到的对象的类型。由于 RRC 在后台工作,我们无法使用常规的 Realm 对象,因此我们可以创建不属于任何 Realm 的对象的副本,或者将对象映射到另一种类型的“实体”U
每个 RRC 的操作都被排入队列,以避免对 willChangeResults
和 didChangeResults
进行的无序调用。每个 RRC 都有自己的队列。
注意: T
和 U
可以是同一类型,那么 RRC 将返回 T
对象的副本,但不包括在任何 Realm 中。
filter
为何物? 您可能会问,如果 RealmRequest
已经有了 NSPredicate
来过滤结果,为什么 RRC 仍然接受过滤函数?嗯,非常简单
RealmRequest
的第一个SortDescriptor
。否则将引发异常。
SortDescriptor
,这限制了sectionKeyPath只能是当前对象的属性
// In this example we ask for TaskModel objects in Realm,
// and we want it to map the results to a Task entity,
// this entity defines it's own mapper in `Task.map`
let rrc = RealmResultsController<TaskModel, Task>(request: request, sectionKeyPath: sectionKeypath, mapper: Task.map, filter: MyFilterFunc)
rrc.delegate = self
// With NIL filter, same as before, but we can ignore the
// filter property if we don't want to use it
let rrc = RealmResultsController<TaskModel, Task>(request: request, sectionKeyPath: sectionKeypath, mapper: Task.map)
rrc.delegate = self
// OR without mapper nor filter, this is a special init.
// Since we don't want to change the result type, we say to the RRC that `T` is the same as `U`.
// The filter will be nil.
let rrc = RealmResultsController<TaskModel, TaskModel>(request: request, sectionKeyPath: sectionKeypath)
rrc.delegate = self
RealmResultsControllerDelegate
有4个必须包含的方法
func willChangeResults(controller: AnyObject)
func didChangeObject<U>(object: U, controller: AnyObject, oldIndexPath: NSIndexPath, newIndexPath: NSIndexPath, changeType: RealmResultsChangeType)
func didChangeSection<U>(section: RealmSection<U>, controller: AnyObject, index: Int, changeType: RealmResultsChangeType)
func didChangeResults(controller: AnyObject)
您可以使用以下公共方法访问RRC中的元素
// Returns all the Sections including its objects
public var sections: [RealmSection<U>]
// count of Sections
public var numberOfSections: Int
// Number of Objects in a Section
public func numberOfObjectsAt(sectionIndex: Int) -> Int
//Object at a given indexPath (ideal for cellForRow... in table views )
public func objectAt(indexPath: NSIndexPath) -> U
// Change the filter currently used. IMPORTANT! after calling
// this method you should reload your table `tableView.realoadData()`
public func updateFilter(newFilter: T -> Bool)
这是一个包含四种不同类型的枚举
enum RealmResultsChangeType: String {
case Insert
case Delete
case Update
case Move
}
为了开始接收RealmResultsController
事件,您需要进行初始获取。之后,您将在代理方法中开始接收更改
rrc.performFetch()
为了使RealmResultsController
在Realm中收到更改事件,您必须使用我们的自定义方法。这些在Realm Extension中声明,并且是原始Realm方法的包装器
public func addNotified<N: Object>(object: N, update: Bool = false)
public func addNotified<S: SequenceType where S.Generator.Element: Object>(objects: S, update: Bool = false)
public func createNotified<T: Object>(type: T.Type, value: AnyObject = [:], var update: Bool = false) -> T?
public func deleteNotified(object: Object)
public func deleteNotified<S: SequenceType where S.Generator.Element: Object>(objects: S)
RRC无法检测写入事务内部的单个对象更新。通知对象更改(非添加或创建)是通过调用notifyChange()
的方法通知的。
notifyChange()
是 RealmObject 扩展中的一个方法,以下是其使用示例
let user = User()
user.name = "old name"
realm.write {
realm.addNotified(user)
}
// STUFF GOING ON...
realm.write {
user.name = "new name"
user.notifyChange() //Notifies that there's a change on the object
}
您可以使用RealmRequest检索请求的对象,而无需将其与RealmResultsController关联。它将返回Results<T>
let predicate = NSPredicate(format: "id != 0")
let sortDescriptors = [SortDescriptor(property: "projectID"), SortDescriptor(property: "name")]
let sectionKeypath = "projectID"
let request = RealmRequest<TaskModel>(predicate: predicate, realm: realm, sortDescriptors: sortDescriptors)
//Execute the request
let objects = request.execute()
您还可以让Realm执行某些请求
let objects = realm.execute(request)
在Realm中,当您请求DB中的对象时,您将收到Results<T>
。因此,我们添加了toArray()
方法来将其转换为常用的Array<T>
let objects = realm.objects(TaskModel.self).toArray()
如果您正在使用RRC方法添加/删除对象,您将能够监听所有Realm更改。
只需将观察者添加到对象,如下所示
let object = Object()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "YOUR_FUNC", name: object.objectIdentifier(), object: nil)
objectIdentifier()
是定义在 Object 扩展中的一个方法,将针对给定对象构建一个标识符。其结构为ObjectiveType-PrimaryKeyValue
目前,RRC无法检测通过另一个对象的关联保存的对象引入的更改。
示例
let user = User()
user.id = 123
user.name = "John"
realm.addNotified(user)
let task = Task()
user.name = "Steven" //This change is not going to be notified
task.assignedUser = user
realm.addNotified(task)
// There will be only one notification for the Task object
要使用示例,只需运行以下命令使用 Carthage 安装 Realm 依赖
carthage update --platform iOS
将 /Source
文件夹内的文件复制到您的项目中
更多信息请参见这里
所有源代码均在 MIT 许可证
下授权。
如果您使用了它,我们很高兴得知这一点。