Exception on editing text in NSTableView [duplicate] - macos

I'm showing the contents of an array of strings with an NSTableView via binding through an Array Controller.
I have "NSString" in Class Name in the attributes inspector for the Array Controller and in the Model Key Path of the Array Controller's binding inspector I have the path to my array. And I have the only column of the table bound in its Value section to the Array Controller without Model Key Path specified (it's just an array of strings).
As a result, the array's strings are displayed fine in the table. But I can't edit any of the rows:
2015-06-17 15:48:44.285 ProjectName[9043:123132] An uncaught exception was raised
2015-06-17 15:48:44.285 ProjectName[9043:123132] Error setting value for key path of object five (from bound object <NSTableColumn: 0x618000082d50> identifier: (null)): [<Swift._NSContiguousString 0x608000045d60> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key .
"five" is the fifth string in the array that I was trying to edit. And as you can see there is a gap in "path of" because the Model Key Path is empty for the column's values.
So do I somehow refer to the string itself in the Model Key Path to make the array editable via the table?

The Class Name should absolutely be set to a valid class. The bigger problem is that the array controller doesn't really play nicely with arrays of strings. There's no (reasonable) way to use -setValue:forKey: on a string since the string is itself what's being edited (replaced), not some property (like "displayName").
I know it seems wasteful, but if you really must use an array controller (more on that in a moment), you should just create a class with a string property and set that as the controller's class name and maintain an array of that class instead of plain strings. Say your array of strings represents tags. Make a Tag class with a name property of type String (or NSString). Set your controller's class name to Tag. This way, there's a key path to which to bind.
But if you really don't see yourself needing anything but an array of strings, you could just use the standard (and infinitely more flexible) [NSTableViewDataSource][1] protocol and good old-fashioned actions triggered by buttons (like Add and Remove). This way you're not fighting the Cocoa Bindings / KVC / KVO mechanisms for what in this case amounts to too-primitive a type (string) for a very abstract controller.
As to amount of work, it's almost "six of one half-dozen of the other" but not quite -- I'd go with the "make it a class with a name property" route for two reasons: 1) It's less work than spinning up a whole table controller / data source, and 2) It's likely you'll later wish you had a more extensible class instead of a simple string for a "list of stuff" even if you don't think so now.

Related

In Xcode, is there a way to list only relevant methods for an object?

Is there some way in Xcode to enter an object's name, and then get a list of the methods that can be used with that object, sorted either hierarchically by inheritance or by return value type?
I know you can get a list of methods by pressing Control-Space after entering the object's name in standard bracket messaging syntax; however, this list often contains numerous methods that are not applicable to the given object. As a result, you still have to scroll through a bunch of garbage, and then look up the class definitions for the object, or reference custom object implementations you have created in order to see which methods will work.

NSComboBox Object Types

I'm pretty new to Cocoa, and I have an NSComboBox which I'm populating with an NSComboBoxDataSource. So far so good, but the one thing I haven't been able to figure out is what type of objects can be stored. I've had success with strings, but I'd like to be able to store more info than what is displayed. I've tried storing a custom object which represents what is being listed (clients), but of course nothing is displayed.
You can save any object, in your model.
But for display purpose string will be good. And based on the selection of the string value, you can fetch the entire object ( it may be in arrays or dictionaries). Then anywhere in your gui you can display all the propeties.
As, when you nslog dictionary or array having objects, you see only its memory locations not the values inside the object. You have to again break them to display. So is the case here.

Binding an NSArrayController to NSDictionary allValues

I've encountered a few scenarios where I'd like to show some entries in an NSDictionary in an NSTableView. (My instincts to user an NSDictionaryController are always foiled by the need to make every object implement copyWithZone, which I find to be an absurd requirement that is fatal to usability...)
Instead, I'm trying to bind an NSArrayController to the allValues property of an NSDictionary, with the intent of binding respective columns of the table various properties of the objects in the array. However, I can't find a correct way to specify this binding within Cocoa, via the Controller Key and Model Key Path properties of the array controller.
When I attempt to bind the array directly to allValues, the array controller's arrangedObjects property is constantly empty - even when objects are added to the dictionary, when the addition is enclosed by [dictionary willChangeValueForKey: #"allValues"] and [dictionary didChangeValueForKey: #"allValues"] calls, even after calling setContent: on the array controller after adding the object.
Of course, I found this Stack Overflow thread:
Binding to an NSDictionary's "allValues" array
...and tried various versions of #"#allValues" in the Model Key Path field, but none produced the desired results.
So here's my question: If I have ArrayControllerOne bound to an object, and I'd like to bind ArrayControllerTwo to the allValues property of an NSDictionary property (called "instances") within ArrayControllerOne.selection, what should I enter in the Controller Key and Model Key Path fields?
Thanks in advance...
You must have missed one, because I found that you can bind the content array of an array controller to a dictionary's allValues by using dict.#allValues (no quotes), where dict is the property name of the dictionary. Why this works, I don't know -- I can't find any documentation for this.
BTW, if I add a new key-value pair to the dictionary, I use self.dict = _dict; to get the table view to update.

Cocoa Bindings Model Key Path Division

In my project I have two text fields which are bound to a mutable dictionary. I want to make a third text field that is the first field divided by the second. However when I try to do this inside the Model Key Path in the bindings tab in Interface Builder it says it is invalid. How can I get this to work?
You cannot perform arbitrary arithmetic operations or use arbitrary expressions in a key or key path. A key specifies a property provided by an object, and a key path specifies a sequence of properties. Although there are some variations such as collection operators, they do not apply to your particular setting.
That said, you could try:
Using a custom class instead of a dictionary and exposing a property that represents the arithmetic operation based on those two other properties. The Key-Value Observing Programming Guide has a section on that.
Using a custom value transformer that would transform the dictionary into the result of the arithmetic operation.
Using a category on NSDictionary to expose a property representing the arithmetic operation. I personally think this is overkill and wouldn’t really recommend it.
Not using bindings at all and performing the arithmetic operation directly in your application delegate, window controller, or view controller.

Why would you bind the value of a NSProgressIndicator?

What's the point of binding the value of a NSProgressIndicator to your controller? It never seems to ask the controller for the value, except on startup. The only way to move the NSProgressIndicator seems to be by sending it #increaseBy:, which bypasses my binding. So, why would I bind?!
If your UI's bound value not updating, that means you either bungled the binding or your controller code is not modifying the bound value in a key-value-observing–compliant way. The most common problem is doing fooIvar = val rather than [self setFooIvar:val] or self.fooIvar = val.
Apple's answer to your problem:
[What to do if] Changing the value of a model property programmatically is not reflected in the user interface
If changes made to a model value programmatically are not being reflected in the user interface, this typically indicates that the model object is not key-value-observing compliant for the property, or that you are modifying the value in a manner that is bypassing key-value observing. You should ensure that:
The model class has automatic key-value observing enabled or implements manual key-value observing for the property.
That you are changing the value using an accessor method, or using a key-value-coding compliant method. Changing the value of an instance variable directly does not provide key-value observing change notifications.
If your model property is a collection, that you're modifying the content in a key-value-observing compliant manner. See “My collection controller isn’t displaying the current data” for more information.
For that answer and answers other common problems, see "Troubleshooting Cocoa Bindings."
You should also look at the examples provided by mmalc. They are a valuable resource.

Resources