Bindings/Core Data: Undesired Discovery of a Mythical "Deep Observer"
Bindings/Core Data: Undesired Discovery of a Mythical "Deep Observer"
- Subject: Bindings/Core Data: Undesired Discovery of a Mythical "Deep Observer"
- From: Jerry Krinock <email@hidden>
- Date: Sat, 2 Jan 2010 15:00:43 -0800
I display several to-many relations in a Core Data app in tables via array controllers and Cocoa Bindings. I have a slight problem with the one that displays
Agent <-->> Commands
This table has two columns, both popup menus, which set the two attributes of Command objects. When I select a Command in the table and change either of its attributes, something in Bindings invokes -[Agent setCommandsOrdered:], passing it a new array containing exactly the same objects that it already has; i.e. a copy. (As is commonly done for storing ordered arrays in Core Data, 'commandsOrdered' is related to the unordered set 'commands', by encoding and decoding an -index attribute).
Now, of course setting A=X when A already =X does not hurt anyone; the only reason I noticed this was because it causes the array controller to lose its selection and default to selecting the first Command. So, since I had implemented -setCommandsOrdered anyhow, I added a little test to it, and return without setting if the new array equals current array. This papers over the problem.
Since I'd subclassed this array controller, it was handy to add an observer on the array controller's -selectedObjects and do some debugging. Seeing that result, I then overrode the private method -[NSArrayController _setMultipleValue:forKeyPath:atIndex:]. In the call stack below, you see that _setMultipleValue:forKeyPath:atIndex: is invoked twice, first in #19 and then in #11. In #19, the 'keyPath' and 'multipleValue' parms are the name and new value of the attribute that I set in the table. That is good and expected. But in #11, the 'keyPath' is commandsOrdered and the value is this new copy of the the commandsOrdered array. That's the bad.
Can anyone see what might be going on between #18 and #12? Looks to me like the problem begins might be with #18 noteContentValueHasChanged. The content value of the array didn't change, just an attribute of one of its elements.
For years on this list, developers have asked for a "deep observer", and been told there's no such thing. Unfortunately, I've got one here!
This project has quite a complex data model, and has many, many code lines of business logic, much of it delivered via notifications, custom setters and keyPathsForValuesAffectingKey<> to make everything work pretty. Probably one of these lines are responsible, but I commenting out anything which might be related doesn't help. Searching the project for keyPathsForValuesAffectingCommands turns up only one hit,
+ (NSSet*)keyPathsForValuesAffectingCommandsOrdered {
return [NSSet setWithObjects:
@"commands",
nil] ;
}
and that is expected. There are no +keyPathsForValuesAffectingCommands.
#0 0x001268ff in -[SSYArrayController observeValueForKeyPath:ofObject:change:context:] at SSYArrayController.m:63
#1 0x002b0208 in NSKeyValueNotifyObserver
#2 0x002afca7 in NSKeyValueDidChange
#3 0x002946d0 in -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:]
#4 0x01b84375 in -[NSManagedObject didChangeValueForKey:]
#5 0x0002c5f5 in -[Command setIndex:] at Command.m:115
#6 0x000b09fb in -[SSYManagedObject setWithIndexesArray:forSetKey:] at SSYManagedObject.m:227
#7 0x000c7942 in -[Agent setCommandsOrdered:] at Agent.m:346
#8 0x002b8c99 in _NSSetObjectValueAndNotify
#9 0x01b8126a in -[NSManagedObject setValue:forKey:]
#10 0x002c8ad3 in -[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
#11 0x008cc6da in -[NSArrayController _setMultipleValue:forKeyPath:atIndex:]
#12 0x001275de in -[SSYArrayController _setMultipleValue:forKeyPath:atIndex:] at SSYArrayController.m:285
#13 0x008cb7f5 in -[NSArrayController _setSingleValue:forKeyPath:]
#14 0x002c8aaf in -[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
#15 0x007690d6 in -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:]
#16 0x00768eb0 in -[NSBinder setValue:forBinding:error:]
#17 0x00aee745 in -[NSObjectDetailBinder setMasterObjectRelationship:refreshDetailContent:]
#18 0x00aee61d in -[NSObjectDetailBinder noteContentValueHasChanged]
#19 0x008cc7ac in -[NSArrayController _setMultipleValue:forKeyPath:atIndex:]
#20 0x001275de in -[SSYArrayController _setMultipleValue:forKeyPath:atIndex:] at SSYArrayController.m:285
#21 0x00769211 in -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:]
#22 0x008dd832 in -[NSBinder setValue:forBinding:atIndex:error:]
#23 0x00768d3d in -[_NSValueBinderPlugin applyObjectValue:forBinding:operation:needToRunAlert:error:]
#24 0x00c83a4d in -[NSValueBinder _applyObjectValue:forBinding:canRecoverFromErrors:handleErrors:typeOfAlert:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:]
#25 0x00c838a3 in -[NSValueBinder applyDisplayedValueHandleErrors:typeOfAlert:canRecoverFromErrors:discardEditingCallback:otherCallback:callbackContextInfo:didRunAlert:]
#26 0x00768647 in -[NSValueBinder performAction:]
#27 0x007683f6 in -[_NSBindingAdaptor _objectDidTriggerAction:bindingAdaptor:]
#28 0x00768333 in -[_NSBindingAdaptor objectDidTriggerAction:]
#29 0x0076c6d9 in -[NSControl sendAction:to:]
#30 0x007681ba in -[NSCell _sendActionFrom:]
#31 0x0068cf86 in -[NSApplication sendAction:to:from:]
#32 0x0068ce39 in -[NSMenuItem _corePerformAction]
#33 0x0068cb2a in -[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:]
#34 0x0068ca16 in -[NSMenu performActionForItemAtIndex:]
#35 0x0068c9c9 in -[NSMenu _internalPerformActionForItemAtIndex:]
#36 0x0068c92f in -[NSMenuItem _internalPerformActionThroughMenuIfPossible]
#37 0x0068c873 in -[NSCarbonMenuImpl _carbonCommandProcessEvent:handlerCallRef:]
#38 0x00680f79 in NSSLMMenuEventHandler
#39 0x03370e29 in DispatchEventToHandlers
#40 0x033700f0 in SendEventToEventTargetInternal
#41 0x03392981 in SendEventToEventTarget
#42 0x033bee3b in SendHICommandEvent
#43 0x033e3b20 in SendMenuCommandWithContextAndModifiers
#44 0x033e3ad7 in SendMenuItemSelectedEvent
#45 0x033e39d3 in FinishMenuSelection
#46 0x03564b82 in PopUpMenuSelectCore
_______________________________________________
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