简体   繁体   English

CoreStore如何观察数据库中的更改

[英]CoreStore how to observe changes in database

I need to observe changes of an Entity after import occurred. 导入后,我需要观察Entity更改。

Currently I have next logic: 目前,我有下一个逻辑:

  1. Save Entity with temp identifier ( NSManagedObject.objectId ) to local core data storage. 将具有临时标识符( NSManagedObject.objectId )的Entity保存到本地核心数据存储中。
  2. Send Entity to the server via Alamofire POST request. 通过Alamofire POST请求将Entity发送到服务器。
  3. Server generates JSON and reply with the almost the same Entity details but with modified identifier which was NSManagedObject.objectId previously. Server生成JSON并使用几乎相同的Entity细节进行回复,但具有先前已修改的标识符NSManagedObject.objectId So the local one Entity id will be updated with server id. 因此,本地一个实体ID将使用服务器ID更新。
  4. Now when I received new JSON I do transaction.importUniqueObjects . 现在,当我收到新的JSON时,我执行transaction.importUniqueObjects

At this step I want to inform my datasource about changes. 在这一步,我想通知我的数据源有关更改的信息。 And refetch data with updated identifiers. 并使用更新的标识符重新获取数据。

So my DataSource has some Entities in an array, and while I use this datasource to show data it's still static information in that array which I fetched before, but as you see on the step number 4 I already updated core data storage via CoreStore import and want DataSource's array to be updated too. 因此,我的DataSource在一个数组中有一些Entities ,虽然我使用此数据源显示数据,但它仍然是我之前获取的那个数组中的静态信息,但是正如您在步骤4上看到的那样,我已经通过CoreStore导入和更新了核心数据存储希望DataSource的数组也被更新。

I found some information regarding ListMonitor in CoreStore and tried to use it. 我在CoreStore中找到了有关ListMonitor的一些信息,并尝试使用它。 As I can see this method works when update comes 如我所见,当更新到来时,此方法有效

func listMonitorDidChange(_ monitor: ListMonitor) func listMonitorDidChange(_ monitor:ListMonitor)

but I try to refetch data somehow. 但我尝试以某种方式重新获取数据。 Looks like monitor already contains some most up to date info. 监视器似乎已经包含一些最新信息。

but when I do this: 但是当我这样做时:

func listMonitorDidChange(_ monitor: ListMonitor<MyEntity>) {

    let entities = try? CoreStore.fetchAll(
                From<MyEntity>()
                    .orderBy(.ascending(\.name))
            ) // THERE IS STILL old information in database, but monitor instance shows new info.
    }

And then code became like this: 然后代码变成这样:

func listMonitorDidChange(_ monitor: ListMonitor<MyEntity>) {

        var myEntitiesFromMonitor = [MyEntity]()

        for index in 0...monitor.numberOfObjects() {
            myEntitiesFromMonitor.append(monitor[index])
        }

        if myEntitiesFromMonitor.count > 0 {
            // HERE we update DataSource
            updateData(with: myEntitiesFromMonitor) 
        }

    }

not sure if I am on the right way. 不确定我的方法是否正确。

Please correct me if I am wrong: 如果我错了,请纠正我:

As I understood each time core data gets updated with new changes, monitor gets updated as well. 据我了解,每次使用新更改更新核心数据时,监视器也会更新。 I have not dive deep into it how this was made, via some CoreData context notification or whatever but after you do something via CoreStore transaction, such as create or update or delete object or whatever you want, monitor gets update. 我还没有通过一些CoreData上下文通知或其他方式深入了解它是如何实现的,但是在您通过CoreStore事务执行了某些操作(例如创建或更新或删除对象或您想要的任何对象)之后,监视器将得到更新。 Also it has callback functions that you need to implement in your class where you want to observe any changes with data model: 它还具有您需要在您的类中实现的回调函数,您想在该类中观察数据模型的任何变化:

Your classes such as datasource or some service or even some view controller (if you don't use any MVVP or VIPER or other design patterns) need to conform to ListObserver protocol in case you want to listen not to just one object. 您的类(例如数据源,某些服务或什至某些视图控制器(如果您不使用任何MVVP或VIPER或其他设计模式))需要符合ListObserver协议,以防您不想只听一个对象。

here are that functions: 这是这些功能:

    func listMonitorDidChange(monitor: ListMonitor<MyPersonEntity>) {
        // Here I reload my tableview and this monitor already has all needed info about sections and rows depend how you setup monitor.
        // So you classVariableMonitor which I provide below already has up to date state after any changes with data.
    }



    func listMonitorDidRefetch(monitor: ListMonitor<MyPersonEntity>) {
        // Not sure for which purposes it. I have not received this call yet
    }



typealias ListEntityType = ExerciseEntity

let classVariableMonitor = CoreStore.monitorSectionedList(
    From<ListEntityType>()
    .sectionBy(#keyPath(ListEntityType.muscle.name)) { (sectionName) -> String? in
        "\(String(describing: sectionName)) years old"
    }
        .orderBy(.ascending(\.name))
        .where(
            format: "%K == %@",
            #keyPath(ListEntityType.name),
            "Search string")
    )

All other thing documented here so you can find info how to extract info from monitor in your tableview datasource function. 此处记录所有其他内容因此您可以在tableview数据源功能中找到如何从监视器提取信息的信息。

Thanks @MartinM for suggestion! 感谢@MartinM的建议!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM