fatbobman / blogComments

1 stars 0 forks source link

在 CoreData 中使用持久化历史跟踪 | 肘子的Swift记事本 #83

Open fatbobman opened 3 years ago

fatbobman commented 3 years ago

https://fatbobman.com/posts/persistentHistoryTracking/

本文介绍了 CoreData 的 Persistent History Tracking 功能。详细讲解了从响应、提取、合并到清除的全过程处理方式,并提供了演示代码供读者使用。

i-tengfei commented 2 years ago

感恩,非常有价值的文章,受益匪浅。 另外,我对 NSManagedObjectContext.queryGenerationTokenNSManagedObjectContext.setQueryGenerationFrom 不太理解,大佬能否帮忙解惑?

fatbobman commented 2 years ago

@i-tengfei 感恩,非常有价值的文章,受益匪浅。 另外,我对 NSManagedObjectContext.queryGenerationTokenNSManagedObjectContext.setQueryGenerationFrom 不太理解,大佬能否帮忙解惑?

Core Data从持久化存储获取的数据,在没有明确要求的情况下,会使用惰值的方式提供给上下文(Fault),这种情况下,在只有一个上下文时没有什么问题。每次持久化存储中的数据发生变化,都必须通过该上下文。代码获取到的数据在对惰值进行填充时,数据始终会保持稳定。 但在多上下文状态下(网络同步状态也可以算作是多上下文状态),一个上下文获取到的数据,在fire时,并不能保证数据是qurey时的内容,因为持久化存储中的数据,可能被另一个上下文或持久化存储协调器(批处理)进行了改动。这种情况在获取排序数据时会很明显。在List中query时,数据A排在第20位,但滚动到A时(对A进行数据填充),A的数据因为被改变应该排到其他的位置。在数据不稳定的情况下,除了行为可能与预期有出入外,有时app也会崩溃。 为了解决这种情况,苹果提供了setQueryGenerationFrom,将查询结果固定到某个时间点的快照数据(也就是说,填充时会使用快照数据的内容,而不从持久化存储中获取)。这样就可以避免上面的情况发生。 queryGenerationToken 就是获取时间点的令牌。setQueryGenerationFrom就是将查询结果pin到该时间点上。 在以下几种情况下,Core Data会自动生成新的令牌,并生成新的快照: 在上下文上使用save 对上下文进行merge 在上下文上使用reset 用代码setQueryGenerationFrom重新设置。

在本文中持久化历史跟踪中,或者其他例如通过网络进行同步的情况下,通过锁定到快照,可以避免因此而产生的系统不稳定。 使用了上述命令,几乎不会让你的app发生可感知的变化。主要是解决稳定性的问题。

当然,如果你将container.viewContext.automaticallyMergesChangesFromParent设置为false,快照的作用就会非常的明显了。 即使持久化的数据发生了变化(例如数据已经被删除或修改),除非你的代码显示合并,否则UI上显示的数据将不会发生改变,浏览这些数据也不会导致app崩溃。

i-tengfei commented 2 years ago

@fatbobman Core Data从持久化存储获取的数据,在没有明确要求的情况下,会使用惰值的方式提供给上下文(Fault),这种情况下,在只有一个上下文时没有什么问题。每次持久化存储中的数据发生变化,都必须通过该上下文。代码获取到的数据在对惰值进行填充时,数据始终会保持稳定。 但在多上下文状态下(网络同步状态也可以算作是多上下文状态),一个上下文获取到的数据,在fire时,并不能保证数据是qurey时的内容,因为持久化存储中的数据,可能被另一个上下文或持久化存储协调器(批处理)进行了改动。这种情况在获取排序数据时会很明显。在List中query时,数据A排在第20位,但滚动到A时(对A进行数据填充),A的数据因为被改变应该排到其他的位置。在数据不稳定的情况下,除了行为可能与预期有出入外,有时app也会崩溃。 为了解决这种情况,苹果提供了setQueryGenerationFrom,将查询结果固定到某个时间点的快照数据(也就是说,填充时会使用快照数据的内容,而不从持久化存储中获取)。这样就可以避免上面的情况发生。 queryGenerationToken 就是获取时间点的令牌。setQueryGenerationFrom就是将查询结果pin到该时间点上。 在以下几种情况下,Core Data会自动生成新的令牌,并生成新的快照: 在上下文上使用save 对上下文进行merge 在上下文上使用reset 用代码setQueryGenerationFrom重新设置。

在本文中持久化历史跟踪中,或者其他例如通过网络进行同步的情况下,通过锁定到快照,可以避免因此而产生的系统不稳定。 使用了上述命令,几乎不会让你的app发生可感知的变化。主要是解决稳定性的问题。

当然,如果你将container.viewContext.automaticallyMergesChangesFromParent设置为false,快照的作用就会非常的明显了。 即使持久化的数据发生了变化(例如数据已经被删除或修改),除非你的代码显示合并,否则UI上显示的数据将不会发生改变,浏览这些数据也不会导致app崩溃。

明白了,解释得好清楚,再次感谢,祝节日快乐。

fatbobman commented 2 years ago

明白了,解释得好清楚,再次感谢,祝节日快乐。

不客气。新年快乐

beader commented 2 years ago

新手请教个问题: 请问 Transaction 是在数据持久化到数据库之后产新手请教个问题: 请问 Transaction 是在数据持久化到数据库之后产生的,还是在持久化到数据库之前产生的?生的,还是在持久化到数据库之前产生的?

fatbobman commented 2 years ago

新手请教个问题: 请问 Transaction 是在数据持久化到数据库之后产新手请教个问题: 请问 Transaction 是在数据持久化到数据库之后产生的,还是在持久化到数据库之前产生的?生的,还是在持久化到数据库之前产生的?

是在持久化之后产生的。

davidleee commented 2 years ago

你好,想请教两个问题:

fatbobman commented 2 years ago

当 app 退到后台后,同步至多可以维持 30秒。 或许你可以通过使用 background task 让app 在后台可以继续同步。 https://developer.apple.com/documentation/backgroundtasks 在 WWDC 2022 的 Digital Lounges 中,苹果工程师也是这么建议的。我目前没有亲自尝试过。

image
davidleee commented 2 years ago

@fatbobman 当 app 退到后台后,同步至多可以维持 30秒。 或许你可以通过使用 background task 让app 在后台可以继续同步。 https://developer.apple.com/documentation/backgroundtasks 在 WWDC 2022 的 Digital Lounges 中,苹果工程师也是这么建议的。我目前没有亲自尝试过。

image

感谢解答,原本还以为 CloudKit 已经做了这方面的工作。

fatbobman commented 2 years ago

不客气

2022年6月30日 15:11,David Lee @.***> 写道:

@fatbobman https://github.com/fatbobman 当 app 退到后台后,同步至多可以维持 30秒。 或许你可以通过使用 background task 让app 在后台可以继续同步。 https://developer.apple.com/documentation/backgroundtasks https://developer.apple.com/documentation/backgroundtasks 在 WWDC 2022 的 Digital Lounges 中,苹果工程师也是这么建议的。我目前没有亲自尝试过。 https://user-images.githubusercontent.com/55673881/176601867-74a2b9d5-ac99-4e03-96ce-7ad02dcec515.png 感谢解答,原本还以为 CloudKit 已经做了这方面的工作。

— Reply to this email directly, view it on GitHub https://github.com/fatbobman/blogComments/issues/83#issuecomment-1170852107, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANIYIGKG3DSQOU3NZLBDSJLVRVCDRANCNFSM5F37MTWQ. You are receiving this because you were mentioned.

ChineseHooper commented 1 year ago

谢谢,太解惑了。

letsbondiway commented 4 months ago

I have an app and an app extension. I have a requirement for the extension to access and write data into app's Core Data backend. I assume I can do this using persistent history tracking. And I guess I also need to enable app groups on both the app and the extension and copy the core data db to shared UserDefaults? Or can the persistent history tracking work without app group in this case?

fatbobman commented 4 months ago

@letsbondiway In this case, your app and extension must use the same app group so that they can access the same database file.

mdm508 commented 2 months ago

When my view context saves to cloud kit.....will I receive a notifiaction NSPersistentStoreRemoteChange for that context that caused the save originally.