Read/Write 多线程上的自定义对象
Read/Write custom objects on multiple threads
我需要能够从 Core Data 中获取对象并将它们保存在内存中的可变数组中,以避免不断获取和变慢 UI/UX。问题是我在其他线程上抓取对象。我有时也会在其他线程上写入这些对象。因此,我不能只将 NSManagedObjects
保存在数组中并调用 myManagedObjectContext.performBlock
或 myObject.managedObjectContext.PerformBlock
之类的东西,因为你不应该在线程之间传递 MOC。
我正在考虑使用自定义对象将我需要的数据从 CD 对象中放入。这感觉有点愚蠢,因为我已经为实体创建了 Model/NSManagedObject class,并且由于自定义对象是可变的,它仍然不是线程安全的。这意味着我必须为多个线程上的对象操作做一些类似串行队列的事情?因此,例如,任何时候我想 read/write/delete 一个对象,我都必须将它扔到我的对象 serialQueue.
这一切看起来真的很讨厌,所以我想知道是否有针对此问题或类似问题的通用设计模式?有更好的方法吗?
一种模式是仅传递对象 ID,它们是 NSString
对象,不可变且因此是线程安全的,并在这些 ID 之后在主线程上查询。这样每个 NSManagedObject
都将属于适当的线程。
或者,您可以使用 mergeChangesFromContextDidSaveNotification,它将使用在辅助线程上所做的更改来更新主线程中的对象。不过,您仍然需要获取新对象。
"caveat" 是您需要保存次要上下文才能获得这样的通知。此外,在应用合并后,主线程中任何新创建但未保存的对象都将丢失 - 但是,如果您的主线程仅使用 CoreData
个对象,这可能不会造成问题。
我怀疑您是否需要在 Core Data 和您的 UI 之间自定义对象。有更好的答案:
- 您的 UI 应该从与主线程关联的托管对象中读取(听起来您正在这样做)。
- 当您在另一个线程上进行更改时,这些更改将更新主线程上的对象。这就是 Core Data 的设计目的。
- 您只需要聆听这些变化并让您的 UI 对其做出反应。
有几种方法可以做到这一点:
NSFetchedResultsController
。有点像你的可变数组,但有一个委托,它会在对象发生变化时发出通知。强烈推荐
- 监听您在 UI 中显示的 属性 上的 KVO 更改。每当 属性 更改时,您都会收到 KVO 通知并可以对其做出反应。代码更多,但重点也更窄。
- 通过
NSNotification
中心监听 NSManagedObjectContextDidSaveNotification
事件并对通知做出反应。正在更改的对象将在通知的 userInfo
中。
在这三个选项中,使用 NSFetchedResultsController
通常是正确答案。当它到位时,您只需更改其他线程上需要更改的内容,保存上下文即可完成。 UI 会自行更新。
我需要能够从 Core Data 中获取对象并将它们保存在内存中的可变数组中,以避免不断获取和变慢 UI/UX。问题是我在其他线程上抓取对象。我有时也会在其他线程上写入这些对象。因此,我不能只将 NSManagedObjects
保存在数组中并调用 myManagedObjectContext.performBlock
或 myObject.managedObjectContext.PerformBlock
之类的东西,因为你不应该在线程之间传递 MOC。
我正在考虑使用自定义对象将我需要的数据从 CD 对象中放入。这感觉有点愚蠢,因为我已经为实体创建了 Model/NSManagedObject class,并且由于自定义对象是可变的,它仍然不是线程安全的。这意味着我必须为多个线程上的对象操作做一些类似串行队列的事情?因此,例如,任何时候我想 read/write/delete 一个对象,我都必须将它扔到我的对象 serialQueue.
这一切看起来真的很讨厌,所以我想知道是否有针对此问题或类似问题的通用设计模式?有更好的方法吗?
一种模式是仅传递对象 ID,它们是 NSString
对象,不可变且因此是线程安全的,并在这些 ID 之后在主线程上查询。这样每个 NSManagedObject
都将属于适当的线程。
或者,您可以使用 mergeChangesFromContextDidSaveNotification,它将使用在辅助线程上所做的更改来更新主线程中的对象。不过,您仍然需要获取新对象。
"caveat" 是您需要保存次要上下文才能获得这样的通知。此外,在应用合并后,主线程中任何新创建但未保存的对象都将丢失 - 但是,如果您的主线程仅使用 CoreData
个对象,这可能不会造成问题。
我怀疑您是否需要在 Core Data 和您的 UI 之间自定义对象。有更好的答案:
- 您的 UI 应该从与主线程关联的托管对象中读取(听起来您正在这样做)。
- 当您在另一个线程上进行更改时,这些更改将更新主线程上的对象。这就是 Core Data 的设计目的。
- 您只需要聆听这些变化并让您的 UI 对其做出反应。
有几种方法可以做到这一点:
NSFetchedResultsController
。有点像你的可变数组,但有一个委托,它会在对象发生变化时发出通知。强烈推荐- 监听您在 UI 中显示的 属性 上的 KVO 更改。每当 属性 更改时,您都会收到 KVO 通知并可以对其做出反应。代码更多,但重点也更窄。
- 通过
NSNotification
中心监听NSManagedObjectContextDidSaveNotification
事件并对通知做出反应。正在更改的对象将在通知的userInfo
中。
在这三个选项中,使用 NSFetchedResultsController
通常是正确答案。当它到位时,您只需更改其他线程上需要更改的内容,保存上下文即可完成。 UI 会自行更新。