Sorting on a table view of a managed object - debugger throws exception
-
Folks;
10.5.7 - 10.5 SDK - target 10.4
I have a managed core data entity working pretty nicely.
I can display values in a tableView.... blah-blah....
Clicking on table column headers does as expected IN RELEASE versions
for both Tiger and Leopard.
However, in the debugger a click on table column header causes an objc-
exception.
If I step thru eventually I can survive and proceed
Error setting value for key path value of object <MyAppDelegate:
0x852600> (from bound object <MyArrayController: 0x3cbe30>[entity:
MyEntity, number of selected objects: 1](null)): [< MyAppDelegate
0x852600> setValue:forUndefinedKey:]: this class is not key value
coding-compliant for the key code.
I know, I know stop hitting yourself on the head with a hammer....
It just bugs me - why?
Have I done something wrong somewhere?
Is this a known bug?
Steve -
On Jul 2, 2009, at 01:10, Steve Cronin wrote:
> 10.5.7 - 10.5 SDK - target 10.4
> I have a managed core data entity working pretty nicely.
> I can display values in a tableView.... blah-blah....
> Clicking on table column headers does as expected IN RELEASE
> versions for both Tiger and Leopard.
>
> However, in the debugger a click on table column header causes an
> objc-exception.
> If I step thru eventually I can survive and proceed
>
> Error setting value for key path value of object <MyAppDelegate:
> 0x852600> (from bound object <MyArrayController: 0x3cbe30>[entity:
> MyEntity, number of selected objects: 1](null)): [< MyAppDelegate
> 0x852600> setValue:forUndefinedKey:]: this class is not key value
> coding-compliant for the key code.
>
> I know, I know stop hitting yourself on the head with a hammer....
>
> It just bugs me - why?
> Have I done something wrong somewhere?
> Is this a known bug?
I love this error message because it is clearly packed with
information, yet it is practically impossible to interpret without
some hints.
What happened is that something tried to set MyEntity's 'code'
property to nil, but the property has a scalar value type, so
setNilValueForKey: was called instead of the usual automatic object-to-
scalar transformation. You haven't implemented setNilValueForKey:, so
the default behavior is to call setValue:forUndefinedKey: instead,
which threw the exception you saw.
This is discussed a little bit in here:
http://developer.apple.com/documentation/Cocoa/Conceptual/CoreDataUtilityTu
torial/Articles/06_runClass.html#/
/apple_ref/doc/uid/TP40001800-CH234-SW1
but I can't find a better explanation, although I thought there was
one somewhere.
The answer is to implement setNilValueForKey: for managed object
subclasses that have scalar accessors, using the pattern shown in the
above tutorial.
If you actually do this, you can set a breakpoint there where it
detects this key, and you might even find out why something is trying
to set your property to nil. One reason it can happen is that when an
object is deleted or faulted out, it can have all its properties
forced to nil. But not always. -
Quincy;
Hey thanks for some useful data!
BUT it is not what is happening in this case.
I have a base class MyManagedObject that all entities are derived from.
MyManagedObject has the - setNilValueForKey: method defined.
I set a breakpoint there and a log message as well. Neither are ever
called.
I have an array controller whose sort descriptors are bound in IB.
This appears to work because the initial display of the table is
ordered accordingly.
There is no sort key nor selector specified in IB for the table column.
The table column value is bound in IB to the array controller.
Below is the full trace when I click on the table column header...
Thanks for your time!
Steve
#0 0x93b63e17 in objc_exception_throw
#1 0x9577bbd1 in -[NSException raise]
#2 0x91b0abb0 in _NSSetValueAndNotifyForUndefinedKey
#3 0x919f98c7 in _NSSetUsingKeyValueSetter
#4 0x919f935e in -[NSObject(NSKeyValueCoding) setValue:forKey:]
#5 0x91a7df81 in -[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
#6 0x9453332d in -[NSBinder
_setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error
:]
#7 0x945330de in -[NSBinder setValue:forBinding:error:]
#8 0x9455c8e6 in -[NSControllerConfigurationBinder
controller:didChangeToSortDescriptors:]
#9 0x9455c7ff in -[_NSBindingAdaptor
controller:didChangeToSortDescriptors:]
#10 0x94543aa5 in -[NSArrayController setSortDescriptors:]
#11 0x919f935e in -[NSObject(NSKeyValueCoding) setValue:forKey:]
#12 0x91a7df81 in -[NSObject(NSKeyValueCoding) setValue:forKeyPath:]
#13 0x9453332d in -[NSBinder
_setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error
:]
#14 0x945330de in -[NSBinder setValue:forBinding:error:]
#15 0x94544670 in -[NSTableBinder tableView:didChangeToSortDescriptors:]
#16 0x945445c8 in -[_NSBindingAdaptor
tableView:didChangeToSortDescriptors:]
#17 0x944a0804 in -[NSTableView setSortDescriptors:]
#18 0x9481a561 in -[NSTableView _changeSortDescriptorsForClickOnColumn:]
#19 0x9455332a in -[NSTableHeaderView
_trackAndModifySelectionWithEvent:onColumn:stopOnReorderGesture:]
#20 0x94552b47 in -[NSTableHeaderView mouseDown:]
#21 0x94365133 in -[NSWindow sendEvent:]
#22 0x94331cd9 in -[NSApplication sendEvent:]
#23 0x9428f62f in -[NSApplication run]
#24 0x9425c834 in NSApplicationMain -
On Jul 2, 2009, at 09:41, Steve Cronin wrote:
> BUT it is not what is happening in this case.
Do you in fact have a "code" property? On the app delegate? What's
does it's @property (or accessor prototype) look like? -
Quincey;
Do you in fact have a "code" property? On the app delegate? What's
does it's @property (or accessor prototype) look like?
The 'code' property is declared on an entity: MyEntity.
The accessors were created by XCode itself using the 'Copy Method
Declaration/Implementation to Clipboard'
- (NSString *)code {
NSString * tmpValue;
[self willAccessValueForKey: @"code"];
tmpValue = [self primitiveValueForKey: @"code"];
[self didAccessValueForKey: @"code"];
return tmpValue;
}
- (void)setCode:(NSString *)value {
[self willChangeValueForKey: @"code"];
[self setPrimitiveValue: value forKey: @"code"];
[self didChangeValueForKey: @"code"];
}
The accessors work because the table is sorted when first presented.
Sorted according to the sortDescriptor which is declared in
MyAppDelegate and bound using IB to MyArrayController.
SortDescriptor is, of course, an NSArray - which is also named 'code'.
Furthermore this all works peachy in a Release build on either Tiger
or Leopard.
Clicking on tableColumn headers sort just as expected.
But not in Debug build - In Debug if I click on table column header I
get thrown into an error:
Error setting value for key path value of object <MyAppDelegate:
0x852600> (from bound object <MyArrayController:
0x3cbe30>[entity:MyEntity, number of selected objects: 1](null)): [<
MyAppDelegate 0x852600> setValue:forUndefinedKey:]:
Steve -
On Jul 2, 2009, at 19:51, Steve Cronin wrote:
> SortDescriptor is, of course, an NSArray - which is also named 'code'.
Huh? Does the matching name mean something about the MyEntity "code"
property?
> Furthermore this all works peachy in a Release build on either Tiger
> or Leopard.
> Clicking on tableColumn headers sort just as expected.
>
> But not in Debug build - In Debug if I click on table column header
> I get thrown into an error:
> Error setting value for key path value of object <MyAppDelegate:
> 0x852600> (from bound object <MyArrayController:
> 0x3cbe30>[entity:MyEntity, number of selected objects: 1](null)): [<
> MyAppDelegate 0x852600> setValue:forUndefinedKey:]:
When debugging weird bindings errors, I found it impossibly confusing
if the property names weren't unique. It might be worthwhile, if you
want to track this problem down, to change the app delegate "code" to
something else. Also note that there's a property named "value"
mentioned in the error message. Is there really a property of that name?
Possibly your best strategy at this point would be put a
setValue:forUndefinedKey override in your app delegate, that calls
super, just so you can set a breakpoint there and look at the
backtrace when things go wrong.



