I'm working my way through Cocoa Programming for Mac OS X (4th Edition), and, like many others, I'm getting stuck on a challenge; specifically, Chapter 8, Challenge 1. Unable to come to the solution on my own, I tracked down a little help from the Life as Clay blog. I added the solution there but I'm getting the following error:
2013-05-09 00:28:49.049 RaiseMan[58078:303] Error setting value for key path sortDescriptors of object <NSArrayController: 0x7fcee2a51900>[object class: RMPerson, number of selected objects: 1] (from bound object <NSTableView: 0x7fcee2a48750>): [<RMPerson 0x7fcee1c5c870> valueForUndefinedKey:]: this class is not key value coding-compliant for the key [personName valueForKeyPath:#"length"].
The thing is, in trying to hunt down what's wrong, I've seen this error crop up all over the place on StackOverflow and I've yet to discern what information it's trying to convey about my project. I can't find any correlation between solutions to understand this error message, so I can't use it to figure out what's going on in my code.
So, long story short, I'm not really looking for help with what is specifically wrong with my code, and more trying to find out what this error message actually means, so I can hunt down the problem myself; however, here's what I'm trying to do anyway. If you can tell me not just what's wrong, but also why this error applies to what I'm doing, that would be great.
In this particular instance, I have a TableView bound to an ArrayController. The ArrayController is bound to File's Owner, with employees (an NSMutableArray) as its Model Key Path. employees is an array of RMPerson objects, each of which has two properties: personName (an NSString) and expectedRaise (a float). The first column of the table shows personName from the respective RMPerson; I am attempting to sort the first column using the length of personName as per the challenge. When I sort it using personName as the sort key and caseInsensitiveCompare: as the selector, all is well. This error crops up when I use either [personName valueForKeyPath:#"length"] or personName.length as the sort key and compare: as the selector.
What does “this class is not key value coding-compliant” mean?
Nothing.
The full exception message makes the question more meaningful:
What does “this class is not key value coding-compliant for <key>” mean?
It means that objects of that class do not have a property named <key>, at least as far as Key-Value Coding is concerned, so you can't use KVC to get a value for such a property from them.
Bindings, of which NSArrayController is a vital part, uses KVC to get and set both bound properties and the properties you've bound them to, so trying to bind something to a property that doesn't exist will get you this exception.
You've got a special case of this, though:
…RMPerson …: this class is not key value coding-compliant
for the key [personName valueForKeyPath:#"length"].
What this means is that you tried to use “[personName valueForKeyPath:#"length"]” as a key.
Strictly speaking, KVC will accept as a key pretty much anything that doesn't have a period in it, but in practice, very few objects recognize any key that isn't an identifier, and all of them (except NSDictionary) expect keys to at least be single words. An Objective-C message expression is not a valid key and cannot be part of a key path.
I'm guessing that you actually pasted “[personName valueForKeyPath:#"length"]” into a Model Key Path field in your nib—for an array controller's sortDescriptors binding, from the looks of it. That won't work. The Model Key Path field expects the key path itself, alone.
personName.length would be a valid key path, but assuming that your RMPersons' names are strings, that isn't going to get you an array of sort descriptors, so you can expect the array controller to choke on the array of numbers.
Whatever you're trying to do (sort by length of name?), you should ask another question about that.
When I sort it using personName as the sort key and caseInsensitiveCompare: as the selector, all is well. This error crops up when I use either [personName valueForKeyPath:#"length"] or personName.length as the sort key and compare: as the selector.
The selector isn't important.
Pay attention to whether something expects a key path or just a key—the distinction is subtle, but app-breakingly important. A sort descriptor requires a single key.
It means you are trying to access/set the value of the object by it's key but that it doesn't have any key-value pair.
In your case, you are trying to set the value of an NSMutableArray by it's key, which is not possible.
So , if you found this "Class is not coding value complient" strange error with some IBOutlet variable name not present in your Project, Try Delete app and Reinstall it Again on Simulator.
Worked for Me!
Related
I am looking into using Google Protobuffers for delta messaging. Meaning I only want to send out the changed values of my domain object.
But that exposes a problem with the protocol for this purpose. I can easily just omit the properties that have not changed, and that will present us with a compact message.
But what about properties that change value from _something_ to null? There is no way to distinguish between these two scenarios in a protocol buffer.
What have others done here? I am looking at a few different solutions:
Add a meta property to all objects, that is an array of int. In case any of the properties should change to null, include the field number in this array. If no properties change, then the meta property is just omitted and doesn't take up bandwidth in the message.
Add a meta property that is a bit mask, but works like the array mentioned in option 1. This might be harder for clients to understand though.
Use a standard way that I haven't been able to find yet.
BR Jay
Protobuf 3 isn't very well suited for this. But in protobuf 2, you can have a field that is present but has value of null.
Because protobuf 2 isn't going to disappear any time soon, I'd suggest just use that for this kind of purposes.
I just wanted to post a follow-up on this and explain what I did.
As #jpa correctly pointed out protobuffers are not made for delta-compression.
So the way I solved it was to use some meta properties and rely on that convention. I have a close partnership with the people consuming the data, so conventions can be agreed upon.
Values that are set specifically to null
I have added an int array to the messages. This int array is empty most of the time and does not have an impact on the message size. When a property is set to null, I will add the property tag to this array and that way indicate that it has specifically been set to null in that message update.
Arrays that are emptied
This works in the same way as the nulls array. I have added an int array to the messages. This int array is empty most of the time and does not have an impact on the message size. When an array is emptied, I will add the property tag to this array and that way indicate that it has specifically been emptied that message update.
Objects that are deleted
To indicate that an object has been deleted, I have added a boolean property indicating that the object has been deleted. When the object is deleted I will set this value to true, and otherwise null, so it doesn't take up space in the message. The resulting message is the key identifier for that object and the boolean indicating that it is deleted.
It requires that the convention is understood by the clients but otherwise it works pretty well.
I need to generate Id for child object of my document. What is the current syntax for generating document key?
session.Advanced.Conventions.GenerateDocumentKey(document) is not there anymore. I've found _documentSession.Advanced.DocumentStore.Conventions.GenerateDocumentKey method but its' signature is weird: I am okay with default key generation algorithm I just want to pass an object and receive an Id.
The default implementation of GenerateDocumentKey is to get the "dynamic tag name" for the class, and append a slash. For example, class Foo would turn into Foos/ which then goes through the HiLoKeyGenerator so that ids can be assigned on the client-side without having to consult the server each time.
If you really want this behavior, you could try to use the HiLoKeyGenerator on your own, but have you considered something simpler? I don't know what your model is, but if the child thing is fully owned by the containing document (which it should be, to be in the same document) have you have several much easier options:
Just use the index within the collection
Keep a int NextChildThingId property on the document and increment that every time you add a ChildThing
Just use a Guid, although those are no fun to read, type, look at, compare, or speak to someone over the phone.
OK, so here's my situation :
I've got an NSDictionary, let's call it : myItem.
myItem.valueNames contains the values that I want to show up in the popup
myItem.values contains the values the popup must return (e.g. for valueName[0] -> value[0], and so on)
myItem.value contains the current value
How am I suppose to bind that? Even though I've studied the official reference, it still looks a bit obscure...
I'm currently binding :
myItem.valueNames to Content
myItem.values to Content Objects
myItem.value to Selected Value
and... all I've managed is that it shows the valueNames.
Any ideas?
Your model is a little strange to me. I wouldn't use an NSDictionary, I'd use a custom subclass with KVC/KVO compliant properties for each of these. Also, if the name of each value is a property of the value object itself, there's no need for a separate valueNames property. So, with that change, I'd do this:
Bind Content to modelObject with a key path of values
Bind Content Values to modelObject with a key path of values.name
Bind Selected Object to modelObject (or yourControllerObject if that makes more sense) with a key path of value (I'd name it selectedValue)
This might be an odd question, but it has actually caused me some headache.
In Object oriented programming, there are accepted names for key concepts. In our model, we have classes with methods and fields. Now, going to the data world:
An instance of a class is called an object.
An instance of a field is called... what?
A value? Isn't the term value a little broad for this? I have been offered "property" as well, but isn't property also part of the model and not the data?
(This is not purely academic, I am actually coding these concepts.)
Updated: Let me take an example. I have a class "Person" with a field "age". If I create 20 Person instances, each such instance is called an object. So far so good. But let's say I take Person "Igor", and set his age to 20. What is the storage location that contains the number 20 now called? Is it a field, or a value, or something else?
Another update: A quote from Pavel Feldman in this related question describes in different words what I tried to describe above:
"I'd say that in class-based OOP field belongs to class and does not have a value. It is so when you look at reflection in c# or java - class has fields, field has type, name, etc. And you can get value of the field from object. You declare field once, in class. You have many objects with same fields but different values."
A field can't be instantiated. A field can only contain a value. The value can be either a primitive/native type or a reference/pointer to an object instance.
As per your update: if the object represents a real world entitiy, then it's often called property. With a "real world entity" I mean something personal/human, e.g. Person, Product, Order, Car, etc. If the object does not represent something personal/human, e.g. List, String, Map, then it's more often called field. That's just what I've observed as far.
Agree with BalusC. However I think what you are asking is what to call the field of an instantiated object. Remember that an object contains both state (data) and operations (methods) you could refer to an object field as state
A field is a field weather you talk about it in the context of a class, or in the context of an object.
class C {
int i; // i is a field
}
and
obj = new C();
obj.i = 7; // obj.i is a field
As opposed to parameter vs argument there is no distinction in terminology for "instantiated" an "uninstantiated" fields.
An instance of a class is an object, a class may contain fields that point to other instantiated objects (or a null pointer). It makes no sense to say an instance of a field, but rather you might talk about the object to which a particular field points to, which may be different for different instances. Or you may talk about the type of a field (which class it belongs to)
Isn't the answer basically that we have no name for values of fields of an instance of a class (or object)?
It's like giving a name to the value returned by a method of an instance of a class...
I guess "state" is the best answer anyway as suggested "BalusC".
Ok so I'm trying to use the JavaScriptSerializer to work with this code. However it crashes when it reaches the last line;
Dim json As New String(sr.Serialize(dt))
I get this error message;
A circular reference was detected
while serializing an object of type
'System.Reflection.Module'.
I would really appreciate any insights that could help solve this problem.
Circular reference means that serialising the object would result in an infinite loop.
For example if you would try to serialize object "A" having a 1 to 1 reference to object "B".
Declare a class containg the data you want to serialize with JSON to solve this issue.
As hkda150 has already said, you could use a class specifically tailored for being serialized.
This will furthermore enable you to have foreign key values serialized instead of having related full objects serialized. Thus, if you are serializing object a which has a property a.SomeB of type B, then you will often want the ID of a.someB to be present in your webpage. Obviously I don't know enough to be able to say if this is relevant in your specific use case.
BTW, If you find yourself doing a lot of mapping between "business objects" and "objects meant for serialization" you may want to consider using AutoMapper.