来自父级的子 NSManagedObjectContext 更新
Child NSManagedObjectContext update from parent
我想在父上下文更新后更新子上下文。
我有一个 NSFetchedResultsController 使用子上下文,然后我想通过它的委托更新 UI - 我不确定这是否完全正确的模式,这就是我现在正在做的:
我创建了一个子上下文,它从支持我的模型的 class 中的 Web 服务更新。这是一个简化的例子:
class Messages {
var pmoc: NSManagedObjectContext!
var delegate: MessagesDelegate?
init() {
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
let moc = appDel.managedObjectContext
let pmoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
pmoc.parentContext = moc
self.pmoc = pmoc
}
func dataToUpdatePrivateContextReceived() {
// Add things to the private moc
self.pmoc.performBlock { () -> Void in
// Create new NSManagedOBject, etc.
self.savePMOC()
}
}
func savePMOC() {
self.pmoc.performBlock { () -> Void in
do {
try self.pmoc.save()
// save main context through an abstraction...
// Inform any delegate a save has taken place
self.delegate?.pmocSavedIntoMain()
} catch let error as NSError {
print("Save pmoc error :\(error.localizedDescription)")
}
}
}
}
protocol MessagesDelegate {
func pmocSavedIntoMain()
}
然后在某些 UIViewController 中,我使用 NSFetchedResultsController 来更新 UITableView,我试图将此控制器与它自己的私有上下文一起使用,因此它的更新不会' t 阻止 UI。
另一个简化的例子:
class ViewController: UIViewController {
var fetchedResultsController: NSFetchedResultsController!
var viewPMOC: NSManagedObjectContext!
let messages = Messages()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
messages.delegate = self
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
let moc = appDel.managedObjectContext
let pmoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
pmoc.parentContext = moc
self.viewPMOC = pmoc
let fr = NSFetchRequest(entityName: "MyEntity")
fr.fetchBatchSize = 20
let sort = NSSortDescriptor(key: "id", ascending: false)
fr.sortDescriptors = [sort]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fr,
managedObjectContext: self.viewPMOC,
sectionNameKeyPath: nil,
cacheName: nil)
self.fetchedResultsController.delegate = self
do {
try self.fetchedResultsController.performFetch()
} catch let error as NSError {
print("vdl fetch error is: \(error.localizedDescription)")
}
}
}
extension ViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(controller: NSFetchedResultsController) {
// dispatch begin updates on maind thread
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
// handle update type on main thread
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
// dispatch end upds on main thread
}
}
extension ViewController: MessagesDelegate {
func pmocSavedIntoMain() {
// what can I do here to get the child context to update from
//parent and thus trigger the fetched results controller to update the view?
}
}
I'm trying to use this controller with it's own private context so
it's updating doesn't block the UI
虽然 FRC 的工作是更新 UI - 这个应该在主线程上,而不是像你提到的那样,一个加载数据的私有上下文。我会把 FRC 放回你的主上下文(当你保存你的子上下文时,它会自动更新),除非你有性能问题,否则就把它留在那里。然后你可以看看更多奇特的东西,但 FRC 旨在通过诸如 batchSize
.
之类的东西来保持高性能
获取的结果控制器需要一个主上下文。
使用此模式摆脱 "choppiness"。
RootContext (private queue) - saves to persistent store
MainContext (main queue) child of RootContext - use for UI (FRC)
WorkerContext (private queue) - child of MainContext - use for updates & inserts
您的 Web 查询完成后,创建工作上下文并更新数据模型。当您 save
时,更改将被推送到主上下文,并且您的 UI 应该通过 FRC 委托进行更新。保存主上下文和根上下文以持久保存。
确保在处理子上下文时始终使用块方法 performBlock
和 performBlockAndWait
。
我想在父上下文更新后更新子上下文。
我有一个 NSFetchedResultsController 使用子上下文,然后我想通过它的委托更新 UI - 我不确定这是否完全正确的模式,这就是我现在正在做的:
我创建了一个子上下文,它从支持我的模型的 class 中的 Web 服务更新。这是一个简化的例子:
class Messages {
var pmoc: NSManagedObjectContext!
var delegate: MessagesDelegate?
init() {
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
let moc = appDel.managedObjectContext
let pmoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
pmoc.parentContext = moc
self.pmoc = pmoc
}
func dataToUpdatePrivateContextReceived() {
// Add things to the private moc
self.pmoc.performBlock { () -> Void in
// Create new NSManagedOBject, etc.
self.savePMOC()
}
}
func savePMOC() {
self.pmoc.performBlock { () -> Void in
do {
try self.pmoc.save()
// save main context through an abstraction...
// Inform any delegate a save has taken place
self.delegate?.pmocSavedIntoMain()
} catch let error as NSError {
print("Save pmoc error :\(error.localizedDescription)")
}
}
}
}
protocol MessagesDelegate {
func pmocSavedIntoMain()
}
然后在某些 UIViewController 中,我使用 NSFetchedResultsController 来更新 UITableView,我试图将此控制器与它自己的私有上下文一起使用,因此它的更新不会' t 阻止 UI。 另一个简化的例子:
class ViewController: UIViewController {
var fetchedResultsController: NSFetchedResultsController!
var viewPMOC: NSManagedObjectContext!
let messages = Messages()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
messages.delegate = self
let appDel = UIApplication.sharedApplication().delegate as! AppDelegate
let moc = appDel.managedObjectContext
let pmoc = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
pmoc.parentContext = moc
self.viewPMOC = pmoc
let fr = NSFetchRequest(entityName: "MyEntity")
fr.fetchBatchSize = 20
let sort = NSSortDescriptor(key: "id", ascending: false)
fr.sortDescriptors = [sort]
self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fr,
managedObjectContext: self.viewPMOC,
sectionNameKeyPath: nil,
cacheName: nil)
self.fetchedResultsController.delegate = self
do {
try self.fetchedResultsController.performFetch()
} catch let error as NSError {
print("vdl fetch error is: \(error.localizedDescription)")
}
}
}
extension ViewController: NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(controller: NSFetchedResultsController) {
// dispatch begin updates on maind thread
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
// handle update type on main thread
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
// dispatch end upds on main thread
}
}
extension ViewController: MessagesDelegate {
func pmocSavedIntoMain() {
// what can I do here to get the child context to update from
//parent and thus trigger the fetched results controller to update the view?
}
}
I'm trying to use this controller with it's own private context so it's updating doesn't block the UI
虽然 FRC 的工作是更新 UI - 这个应该在主线程上,而不是像你提到的那样,一个加载数据的私有上下文。我会把 FRC 放回你的主上下文(当你保存你的子上下文时,它会自动更新),除非你有性能问题,否则就把它留在那里。然后你可以看看更多奇特的东西,但 FRC 旨在通过诸如 batchSize
.
获取的结果控制器需要一个主上下文。
使用此模式摆脱 "choppiness"。
RootContext (private queue) - saves to persistent store
MainContext (main queue) child of RootContext - use for UI (FRC)
WorkerContext (private queue) - child of MainContext - use for updates & inserts
您的 Web 查询完成后,创建工作上下文并更新数据模型。当您 save
时,更改将被推送到主上下文,并且您的 UI 应该通过 FRC 委托进行更新。保存主上下文和根上下文以持久保存。
确保在处理子上下文时始终使用块方法 performBlock
和 performBlockAndWait
。