CoreData and the NSComboBox - xcode

I have a Mac application that uses CoreData. I have 1 entity "Employee" with 2 attributes, employeeName and employeePin. I have a drawer window that is used to add employees as well. I want an NSComboBox to be populated with the employeeName attribute from CoreData but I can't figure it out. Ive got CoreData working like it should but I can't figure out how to bind the NSComboBox with that particular attribute.
I created an Array Controller and set the parameter "Managed Object Context" to the App Delegate with the model key path managedObjectContext but Im not getting the names to pull up in the combo box. How do i get the names to pull up in the combo box. Any and all help is appreciated.

To fully set up the array controller you also need to set the mode to 'Entity Name' in the identity inspector of the array controller and specify this as 'Employee'
After that you need to bind the 'content value' of the combo box(in bindings inspector) to employeeName of the array controller. (arrangedObjects).
i.e in the Bindings inspector,
click on bind :Array controller
Controller Key :arrangedObjects
Model Key Path : employeeName

Related

Problems with cocoa bindings w/ master-detail where the detail contains an array

This is a macOS app, using Core Data, no Documents, and no Storyboards. I'm trying to use NSArrayControllers & bindings to display my data.
The data model 2 entities:
Book (which has attributes like author, title, blurb), and
Chapters (which has attributes like title)
The two entities are connected with a one-to-many relationship:
Book.chapters <—>> Chapter.book.
The app can have multiple books, which it shows in a tableView. Simple enough. I have an Array Controller set up in XCode called "Books Array Controller". I set its Entity as "Book" and check the "prepares content".
It's a master-detail, where one of the properties on the detail is an array to be shown in its own table. And this is what's giving me problems.
I bind the Books Array Controller as follows:
1. The managedObjectContext is bound to Delegate's self.managedObjectContext.
2. The bookListTableView has its Table Content > content bound to "Books Array Controller" controller key = arrangedObjects.
3. And then for each column in the table, I select the textViewCell and bind its value to the "Table Cell View" model key path = objectValue.title, objectValue.author, etc.
4. I have a textView that the "blurb" (attributed string) of the selected book by binding Attributed String to "Books Array Controller" controller key = selection, model key path = blurb.
All of this works just fine.
But I'm having a lot of problems trying to figure out how to display the chapter list in another table. I've tried creating another Array Controller called "Chapters Controller". I set its Entity as "Chapter" and check the "prepares content".
I bind the Chapters Controller as follows:
1. The managedObjectContext is bound to Delegate's self.managedObjectContext. (just like for the other one)
2. The Controller Content > content set is bound to "Books Array Controller" controller key = selection, model key path = chapters.
3. I bind the table's content to the "Chapters Controller" controller key = selection, model key path = chapters.
4. And then for each column in the table, I select the textViewCell and bind its value to the "Table Cell View" model key path = objectValue.title, etc.
Nothing ever shows in that 2nd table, the one for the chapter list. Not even a bunch of "Table View Cell" things. It's empty. I've tried a bunch of variations I won't bore you with. There's clearly something I'm missing. Any help?
The app correctly makes its Book objects, and the Books appear to correctly make their Chapter objects.
———
Update: I've attempted to follow Willeke's advice and am still not doing it right.
Here are the bindings...
Books controller binding:
Chapters Controller binding:
Books TableView binding:
Chapters TableView binding:
The content set of the Chapters array controller is bound to the selection of the Books array controller. When you select a row in the Books table view, the Books array controller's selection has to be synchronized by binding the selections indexes. I usually bind Content to arrangedObjects, Selection Indexes to selectionIndexes and Sort Descriptors to sortDescriptors.
The bindings from the Chapters table view are the same as the Books table view. Bind content of the Chapters table view to arranged objects of the Chapters array controller.

Binding Core Data Entity to NSTableView: Model Key not working

I'm attempting to use Cocoa bindings to populate an NSTableView using Core Data entities. I've arrived at a point where I'm boggled by the behavior of my application. The array controller is in "Entity Name" mode and is using the my "Song" entity.
The table view I am attempting to load the data into has two columns: one for the song name and another for the artist name (the artist is another entity which has a relationship to a song). Through Interface Builder, I have been able to successfully bind the array controller to the table, and setup bindings for the two columns. However, for some reason, one of the columns' bindings is working perfectly (artist name) while the other is not populating at all (song name).
I have gone through each view in the Document Outline and ensured that both columns are configured in exactly the same manner. I've attached some screenshots below showing the binding setup in Interface Builder.
Binding on the NSTableColumn representing the Song Title
Binding on the NSTextField within the NSTableCellView (the one that is not working)
Binding on the NSTextField for Artist Name (the one that is working)
The final (non-functioning) result
Is there an obvious reason why this approach is not working? Any help would be greatly appreciated. I can also provide any additional information that may be needed to answer this question.
It appears you are using a "view" based NSTableView as opposed to the older "cell" based. Each have a different configuration for bindings. In a view based table view you have to bind the tableview content to the array controllers arrangedObjects (see below), you don't have to deal with the individual column bindings that is for cell based table views.
Your remaining bindings look fine.
Just a wild guess. Since you're speaking of the Song entity.
Can it be that you have to bind the song name to objectValue.song.title?
If 'Artist' isn't just an attribute of the 'Song' entity but an entity itself (which it must likely be if it has a relationship to 'Song') then I think you need to have a separate array controller connected to that column in order for it to work properly.

Sharing NSArrayController Between Nibs

I have an Core Data-based iTunes-like app I'm building that has an NSTableView in the main window and allows the user to select items in the table view and perform a "get info", like in iTunes. Currently I'm working on the single-item get info window, which displays when the user selects a single item in the main window (which is in MainMenu.xib) and pressed Cmd-I. This brings up the single-item get info window (in SingleItemGetInfo.xib).
The table view in the main window is populated via bindings to an NSArrayController. If I put an NSArrayController into the SingleItemGetInfo.xib file, I understand that's going to be a different instance of NSArrayController.
So, what's the proper way to bind the fields in the single item get info window to the selection the user has made in the main window's table view?
MainMenu.xib's Array Controller bindings:
Managed Object Context: AppDelegate.self.managedObjectContext
MainMenu.xib's Table View bindings:
Content: Array Controller.arrangedObjects
Selection Indexes: Array Controller.selectionIndexes
Sort Descriptors: Array Controller.sortDescriptors
This will work mostly the same way it does when the master and detail views are in the same window. The primary difference is that you need to bind the selection of the array controller in the detail xib to the selection of the master array controller.
It depends on how you have your app organized as to how you accomplish this. If both views are run by the same object then you can just make the master array controller an outlet connected to the controller (#property IBOutlet NSArrayController *masterArrayController;). Then in the detail xib you can bind the selection of the detail array controller to the selection of the master array controller.
If each view has its own controller you might also consider just passing the managed object from the master view to the detail view. Then you can bind to each of the attributes of the managed object in your xib file (i.e. bind to File's Owner self.detailObject.fullName). If you pass a reference I think all of the changes will go right back into the managed object context.

CoreData Binding and custom Cell

I have an app with a CoreData Database and a NSTableView.
I want to do a customCell with 3 key values from database.
So I create an NSTextFieldCell Class but the binding is only for a key value.
How I can programmatically bind a NSTableColumn with multiple key value ?
Thanks.
Here's one way to do it which foregoes the need to create a custom cell:
1) In IB, drag over an Array Controller to your Objects sidebar. Under the Attributes Inspector, set its "Mode" to Entity Mode, fill in the "Entity Name" with the name of your entity, and check "Prepares Content". Under the Bindings Inspector, set its "Managed Object Context" to managedObjectContext.
2) In IB, convert your table to be view-based. Select the "Table View" and under the Attributes Inspector, select Content Mode: View Based and change number of columns to 1.
3) In IB, select the "Table Column" and bind its Value to the Array Controller representing your object. Controller Key should be "arrangedObjects" and leave the "Model Key Path" blank.
4) In IB, select the text field (Label) in your NSTableView cell. Bind its Value to the Table Cell View. The "Controller Key" can remain blank and set the "Model Key Path" to objectValue.whateverAttributeName
There's an awesome summary and tutorial of view-based tables at Gentle Bytes.
Tim Isted created a wonderful tutorial on how to programmatically create bindings, if that's specifically what you desire at Blog # Tim Isted.

What's the point of the "Controller Key" property in IB in the Inspector > Bindings pane?

Apple says:
An attribute of an NSController object. When binding to an NSController object, you use this field to select the first entry in the key path. The menu associated with this field displays the properties available on the selected controller object as a convenience. You can type the name of the property or simply select it from the provided list.
Can someone explain that in other words?
You are binding a view object to a model property. Something like (schematically):
myTextField.value <=> myModel.textValue.
While you can bind a view property directly to your model object's property like shown above, you really shouldn't. You would miss out on the nice features provided by Apple's controllers (e.g. NSObjectController, NSArrayController, etc.). Instead you should bind your view to a controller which is bound to the model, like:
myTextField.value <=> myObjectController.selection.textValue
and
myObjectController.contentObject <=> myModel
In this setup, myObjectController.selection is a Key-Value binding compatible proxy for myObjectController.contentObject and myObjectController can act as a mediator between the view and the model. Interface Builder makes this separation of concerns explicit because controllers may expose multiple proxies for their bound model (such as NSArrayController's arrangedObjects and selectedObjects). In binding myTextField.value in the example above, you would enter 'selection' in the "Controller Key" field and "textValue" in the "Model Object Keypath" path field.

Resources