Binding an NSArrayController to NSDictionary allValues - cocoa

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.

Related

Exception on editing text in NSTableView [duplicate]

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.

Two NSArrayControllers on one NSManagedObjectContext?

I have two NSArrayControllers in my MainWindow.xib and want to use both of them with CoreData. Both are using entities of the same type from the same data model. These two array controllers are bound each to their own table views (one for generated data, one for stored data).
The first array controller is connected to the managed object context in AppDelegate but what do I do about the second array controller? It doesn't seem it can be connected to the same managed object context. If I compile now I get the error Cannot perform operation without a managed object context for the second array controller.
To answer this question on my own now:
The binding inspector in IB has bindings on NSArrayController for the Managed Object Context. I wasn't completely sure that this is the right way to bind the array controllers but it obviously seems to be so.

Having an NSSet as part of an NSManagedObject in Core Data

I have a class which as its properties has a number of NSSet values. The content of these sets is not stored in Core Data, but comes from another source. They are basically ID strings which are unique. No point in filling up Core Data with them as separate entities.
However, as far as I can see it's not possible to store an NSSet as an attribute of an NSManagedObject. I guess I would need to serialise it into binary data by hand, whenever the object gets stored, and deserialise it when it gets retrieved from the persistent store? The same would also apply to storing other collection classes.
Has anybody else ever come across this issue and is able to give some advice?
You can set the attribute type to 'transformable' and then directly store the set into the attribute. Be sure that all of the contents of the set conform to < NSCoding >.
In Xcode, in the Project Navigator open up the project_name.xcdatamodeld source for the model editor and select the entity in question. Choose Editor in the Xcode menu bar and there is a Create NSManagedObject subclass... item. Make the subclass and use it for extra non-Core Data properties. The subclass becomes part of the model in place of the entity. It retains all of the entity's behaviors.

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.

Cocoa input validation for duplicate name how?

How can I implement this validation in Cocoa?
My Situation is:
Model: An object names Person, with a name property. And an NSArray of Person objects,
View: NSTableView, it uses data-binding to bind with the Person object array. The NSTableView has in-place editing function enabled.
When user finish editing the name in NSTableView, I need check if the Person's name already exists in the Array.
I read the key-value Validation document. It looks KVC will help call validate:error: method on the bound object. So in my case, it should be the Person object. But the Person Object cannot access the whole array, I cannot check for duplication in the method.
Can anyone point me how to use key-value Validation to handle this case?
Thanks!
-Jonny
Take a look at this page in documentation particularly section "User Updates a Value in the User Interface". Hope this helps.

Resources