Realm Swift如何在更新结果时收到通知

时间:2015-10-29 10:44:56

标签: swift notifications realm key-value-observing

我使用Realm结果对象Result<AnObject>作为uitableview的数据源。在不同的视图控制器中有一些晚期API调用,可以加载更多AnObject个对象。我想要的是在更新数据源以更新表视图时收到通知。 我做了一些搜索并且知道我需要使用 KVO ,但我找不到任何关于如何在realm中使用它的示例。我的代码如下所示:

class myViewController: UIViewController, UITableViewDatasource {
    let realm = try! Realm()
    override func viewDidLoad() {
        super.ViewDidLoad()
        var datasource = realm.objects(AnObject.self)
        // I need to some how observe the change of datasource
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return datasource.count
    }
    ...
}

更新 我尝试在它工作之前使用realm.addNotificationBlock(在@joern回答中的方式相同),但是当任何领域对象不仅更新数据类型时,问题就是块将运行。这个表重新加载了太多无意义的时间。

更新2 我的应用程序有一个CalendarViewController,它在上半部分包含一个FSCalenar视图,在下半部分包含一个链接到EventsViewController的容器,该容器具有事件的tableview。 我有很多事件需要很长时间才能从API中获取。所以我对API进行了大约20次调用,每个API都会获得一些事件。并在NSOperationQueue中添加所有调用操作,然后根据我需要首先加载的内容设置操作优先级。因此,每个API调用在完成时都会更新数据源对象。我需要事件tableview然后重新下载。 API调用发生在由CalendarViewController

调用的APIManager类方法中

2 个答案:

答案 0 :(得分:9)

您不必使用KVO。您可以使用Realm的通知功能:

  

Realm实例向其他实例发送通知   每次提交写事务时都会生成线程。这些   通过注册块可以观察到通知:

let token = realm.addNotificationBlock { notification, realm in
    let realm = try! Realm()
    self.datasource = realm.objects(AnObject.self)
    self.tableView.reloadData()
}

只要您对此令牌保持强烈引用,您就会收到通知。

<强>更新

如果您不想使用Realm的通知,您可以在API调用返回结果时发布您自己的通知,然后相应地重新加载表视图:

将您的EventViewController添加到默认NSNotificationCenter并添加操作:

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("didReceiveReloadNotification:"), name: "RELOAD_NOTIFICATION", object: nil)
    ...
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func didReceiveReloadNotification(notification: NSNotification) {
    let realm = try! Realm()
    datasource = realm.objects(AnObject.self)
    tableView.reloadData()
}

然后,只要您的某个API请求操作完成后发布通知:

dispatch_async(dispatch_get_main_queue()) { () -> Void in
    NSNotificationCenter.defaultCenter().postNotificationName("RELOAD_NOTIFICATION", object: nil)
}

答案 1 :(得分:1)

在这里,我正在更新Swift 4+的答案,以获取有关结果更新的通知

第1点:在属性下方声明

 var notificationToken: NotificationToken? = nil
 let results = realmManager.realm.objects(MemberHistory.self)

第2点:您可以在viewWillAppear上添加以下部分,也可以添加一个方法并在ViewWillAppear上调用该方法

{
   notificationToken = results?.observe {(changes: RealmCollectionChange) in
                        switch changes {
                        case .initial(let data):
                            print("initials count - \(data.count)")
                            self.chatTableView.reloadData()

                        case .update(_, let deletions, let insertions, let modifications):


                            if(insertions.count == self.arrMessages?.count)
                            {
                                //This section will execute when the user's first load of messages comes from API, I had used this for my internal purpose
                            }
                            else
                            {
                                self.chatTableView.beginUpdates()
                                self.chatTableView.insertRows(at: insertions.map({ IndexPath(row: $0, section: 0) }),
                                                              with: .none)
                                self.chatTableView.reloadRows(at: modifications.map({ IndexPath(row: $0, section: 0) }), with: .none)
                                self.chatTableView.deleteRows(at: deletions.map({ IndexPath(row: $0, section: 0)}),
                                                              with: .none)
                                self.chatTableView.endUpdates()
                                self.chatTableView.scrollToBottom()
                            }


                        case .error(let error):
                            Toast(text: "Error", duration: Delay.short).show()
                            fatalError("\(error)")
                        }
                    }
                }