Core Data faulting and bindings: recursive KVO notifications?
Core Data faulting and bindings: recursive KVO notifications?
- Subject: Core Data faulting and bindings: recursive KVO notifications?
- From: Dennis Lorson <email@hidden>
- Date: Fri, 28 Mar 2008 00:59:20 +0100
Hi,
I have a Core Data (single-doc) application in which I have a medium-
complex object graph.
In this application, a main entity (Image) forms the master part (they
are displayed in a list), and this entity has several properties.
I use an array controller to manage the Image selection, and I have a
detail view (Inspector, if you will) displaying the properties.
The problem I'm having arises when selecting all images at once
(Command+A), if they are fairly large in number (in my store: ~2000).
This takes an enormous time that is definitely > O(n).
Sampler reveals nothing particular because processing time is
generally divided between many lower-level CD operations (string
creation, etc.)
Upon inspecting the issue closer, it seems that the stack reaches a
large depth (trace > 20.000). Of course, this is some kind of
recursion. The stack recursive pattern is:
#0 0x0002cba2 in -[ImageArrayController
observeValueForKeyPath:ofObject:change:context:] at
ImageArrayController.m:345
#1 0x91abb58e in NSKVONotify
#2 0x91abb58e in NSKVONotify
#3 0x91b6fdec in -[NSObject(NSKeyValueObservingPrivate)
_didChangeValuesForKeys:]
#4 0x937d290d in _PFFaultHandlerFulfillFault
#5 0x9380bf3a in -[NSFaultHandler fulfillFault:withContext:]
#6 0x937d4102 in _sharedIMPL_pvfk_core
#7 0x937d4c3c in -[NSManagedObject valueForKey:]
#8 0x91a8c39a in -[NSObject(NSKeyValueCoding) valueForKeyPath:]
#9 0x91a8c300 in -[NSObject(NSKeyValueCoding) valueForKeyPath:]
#10 0x94de7516 in -[NSArrayController _singleValueForKeyPath:]
#11 0x0002cced in -[ImageArrayController _singleValueForKeyPath:] at
ImageArrayController.m:370
#12 0x91a8c300 in -[NSObject(NSKeyValueCoding) valueForKeyPath:]
#13 0x94daae48 in -[NSBinder
_valueForKeyPath:ofObject:mode:raisesForNotApplicableKeys:]
#14 0x94daaa50 in -[NSBinder
valueForBinding:resolveMarkersToPlaceholders:]
#15 0x94ddff8c in -[NSValueBinder _referenceBindingValue]
#16 0x94ddfd57 in -[NSValueBinder
_adjustObject:mode:observedController:observedKeyPath:context:editableState:adjustState
:]
#17 0x94ddf9e0 in -[NSValueBinder
_observeValueForKeyPath:ofObject:context:]
#18 0x94de10c1 in -[NSTextValueBinder
_observeValueForKeyPath:ofObject:context:]
#19 0x91abb58e in NSKVONotify
#20 0x91a4be45 in -[NSObject(NSKeyValueObservingPrivate)
_notifyObserversForKeyPath:change:]
#21 0x94bcd15e in -[NSController _notifyObserversForKeyPath:change:]
#22 0x94dea920 in -[NSController
observeValueForKeyPath:ofObject:change:context:]
#23 0x94dea479 in -[NSArrayController
observeValueForKeyPath:ofObject:change:context:]
#24 0x0002cca4 in -[ImageArrayController
observeValueForKeyPath:ofObject:change:context:] at
ImageArrayController.m:361
#25 0x91abb58e in NSKVONotify
#26 0x91abb58e in NSKVONotify
........
In which [ImageArrayController observeValue:::] is invoked every time
with the same keypath : @"instrument.magnification", but with a
different image as observable object. Instrument is a NSManagedObject
with float property magnification, and each image has one instrument
(the inverse relationship is 1..n).
The way I interpret this (it could be wrong, I don't have unlimited
insight in private APIs)
- the array controller observes a change in keypath
instrument.magnification of object imageA, and calls super. This is
because observers are bound to the selection key of the controller.
- a NSTextField that is bound to
controller.selection.instrument.magnification receives the
notification. (through NSTextValueBinder)
- the text field asks for the value of the property.
- a Core Data fault fires for the magnification property. I assume
that here, only the properties of Instrument are loaded. Is this
correct?
- some object (I assume the Instrument?) invokes [self
_didChangeValuesForKeys:] because of the fulfilled fault
- since the array controller observes the key, observeValue::: is
invoked again with keyPath instrument.magnification, HOWEVER the image
object is not the same!
This recurses further with all images in the controller selection
until the whole object graph is in-memory. It is much slower (>1
minute on a MBP with 2000 elements in the controller set) than loading
the data in a normal manner, probably because of spread faulting and
the large stack depth.
My question now is, why does this recursiveness occur? Each
instrument has one image relationship in the test scenario, so why is
the same keypath triggered for another image object, if the trigger is
caused by a property of an instrument that is only related to one of
the two images?
Thanks for any advice,
Dennis
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden