Mutliple views for detail in a master-detail interface - objective-c

I am building a preferences pane for an app where the user can add a Web Service to a list (in a tableview on the left) and a form should appear on the right where the user can edit configuration options for the web service (like username or password or API key or tumblr blog name, etc.) I think I'll need different views for different types of service (possibly with different logic for validation and so on).
My question is what is the best way to implement this?
What I've done: I have a NSSplitView with a NSTableView. I have an NSArrayController with it's content bound to the appropriate key in NSUserDefaultsController and the NSTableView bound to it's arrangedObjects and selectionIndexes. Next I've added a NSTabView in the right with it's selectedIndex bound to the NSArrayController's selectedIndex and I'm trying to programatically insert the appropriate views (which I've created as separate custom views in IB) as tabs.
This seems to me to be a not the best approach. I also don't know what to bind the fields in the detail views - is it even possible to use bindings here? How would you solve this problem?

Instead of the NSTabView, create a blank NSView for the inspector (inspectorView). Same idea, but a little simpler.
In tableViewSelectionDidChange, write something like:
newView = ...;
if (inspectorView != [customInspectorView superview]) {
NSView *oldView = [[inspectorView subviews] objectAtIndex:0];
[inspectorView replaceSubview:oldView with:newView];
}
You can bind your fields to servicesArrayController.selection.username and so on.

Related

ArrayController's CoreData selection binding not refreshed across multiple NIB files

I've a hard time getting my Cocoa application to work as expected. It consists of a toolbar in the main.nib and a custom view in a details.nib file. Now I want the user to select an entry in a NSPopupButton in the toolbar and the content of the custom view should be changed accordingly.
To achive this I've added an ArrayController to my main.nib, showing the following configuration:
Furthermore the Managed Object Context is bound to the Model Key Path delegate.managedObjectContext (it is no document based application).
With this configuration the NSPopupButton works just fine and if I add a Label to the toolbar (also in the main.nib) and bind it's value to the selection (Controller Key), name (Key Value Path) the content is refreshed whenever I change the selection.
The Bindings of the NSPopupButton look like shown in the following screenshot:
So in my details.nib I tried the following to achieve the same effect. I've added an ArrayController, whichs Managed Object Context is also bound to the Model Key Path delegate.managedObjectContext. Also the configuration is exactly the same as shown in the above pictures. I've then added a label and bound it's value to the selection (Controller Key), name (Key Value Path) of this ArrayController.
The problem is that the Label only displays the the initial selection after the application did launched correctly. Afterwards, when I change the selection of my NSPopupButton, the label does not change accordingly.
What are my options to get the ArrayController working accross multiple NIB files?
BTW: I've tried to follow this blog post to get it working but it seems I'm missing something here.
Update:
If I replace the Label in the details.nib by a NSTextField and change the text of it, the changes are reflected in the related NSPopupButton entry. So I guess I made something right, but the main problem remains: I can only edit the entry which was loaded during application startup. Switching to another NSPopupButton entry does not change the text in the NSTextField.
Update 2:
I've created a small sample project with exactly the same configuration and uploaded it on GitHub. So feel free to check it out or create a pull request with a solution approach.
It seems you're missing the fact that, when you create the second array controller on the Details.xib it has no relation to the array controller on the MainMenu.xib. They are two separate instances.
When you change the selection on the PopUp the only array controller affected is the one on MainMenu.xib.
You have several options here:
When you create your DetailViewController pass a reference to the array controller on the Controller and bind to that (don't create a new one on the details.xib)
Just use simple KVO to observe the selection on Controller, and programatically change your label value.
Just use simple KVO to observe the selection on Controller and update the array controller on the DetailsViewController to keep them in sync.
your solution here...
As long as you understand what's going on I'm sure you'll find the best solution to your original problem.

How to Reload NSCollectionView

I have NSCollectionView with full of items, have one scenario where after deletion of one item the collection view should be refresh and it should display update items.
I am able to delete item, but collection view is not refreshing,
googled a lot, but got nothing,
NSCollectionView is a subclass of NSView. And you must be knowing MVC design pattern. View is intended only to show the data/values from the model.
In your case you must have some array. You need to update the array and set the content of NSCollectionView programmatically or using Cocoa Bindings.
- (void)setContent:(NSArray *)content;
Also you may need to refresh the view :
[yourCollectionView setNeedsDisplay:YES]
Anoop's suggestion didn't work for, but following did, copied from here
Turns out that the NSCollectionView item views can be refreshed by setting the ItemPrototype, e.g.,
ItemPrototype = new SomeViewController()
This causes all the existing views to be recreated.

Custom NSPopUpButtonCell outlet / bindings

I'm having a problem with a custom NSPopUpButtonCell in a table that's instantiated when the table view is populated via bindings and a NSArrayController.
The pop up button cell is created but when attempting to access the outlet by overriding the pop up button cell's setMenuItem:item method it's nil.
Is this the expected behaviour..?
Should another method be used to replace the menu at creation time?
Basically I need the outlet to link back to my controller (NSWindowController) for that document window so I can customize the NSPopUpButtonCell menu accordingly from the custom popup button when it's populated.
A solution using bindings would be even better - but when overriding setObjectValue: I can see it's only never called with a nil parameter.. using a stock NSPopUpButtonCell results in a properly populated pop up menu, though.
(see also Why is NSPopUpButtonCell showing correctly when only setObjectValue:nil is called).
You don't need to override anything to populate an NSPopUpButtonCell in an NSTableView column. The thing to know is that you set the bindings on the NSTableColumn and not on the cell itself. Typically, you would have an NSArrayController in your xib that is bound to an NSArray containing all the options for the pop-up, and then you would select the column with the pop-up cell and go to it's bindings. Like in this screenshot (note the populated Content, Content Objects, and Selected Object bindings in the inspector on the right):
If you want a working example, you can check out this project I whipped up for another StackOverflow question. There's a bunch of unrelated stuff pertaining to making the NSPopUpButtonCell use NSAttributedStrings, but the bindings in the xib constitute a working example of how to bind an NSTableColumn with a pop-up whose options are populated by bindings.

NSPopUpButton + Bindings + Show All Option

I'm trying to develop a NSPopUpButton that will serve as a filter to some datasource, let's say a NSArrayController that fills a table.
I can bind the NSArrayController from the menu to the selection keypath so the data is properly filtered, no problem with that.
Tricky part is, I want the content of this NSPopUpButton to rely on an NSArrayController using bindings, but I'd like to add a "Show All" menu item, or at least some item that doesn't come from the Core Data and performs some special action other than filtering the table using bindings and core data.
I'm trying to perform something like the NSPopUpButton used by finder in the filter bar, the last item of the menu performs a special action, while the others just filter the result.
I understand that the approach is to forget about bindings and do it everything programmatically, because I believe there's no way to mess up with the NSArrayController and bindings to add this custom menu item that doesn't rely on core data, but since I haven't found anything on the Apple Docs and here, I'd like to share my thoughts... any ideas?
sounds to me like you're looking for the NSContentPlacementTagBindingOption.
you edit the NSMenu that's attached to the NSPopupButton as follows
you then edit the settings on the NSMenuItem you want to have replaced with your array controller contents so that it has a meaningful tag associated with it
you then specify that tag as the content placement tag value on the NSPopupButton's bindings for the content/content* bindings.

Binding NSTableView and NSArrayController together

I have an app controlled by a big controller. In my principal window, I have a button, which when pressed I want to open a new window where data would be stored into an NSTableView.
After reading some documentation, I found something very interesting and useful between NSTableView and NSArrayController.
So I would like to know if it's possible to display data in an NSTableView controlled by a NSArrayController from an NSMutableArray edited in my Controller.
Yes, this is what NSArrayController is for. See Creating a Master-Detail Interface in Cocoa Bindings Programming Topics for full instructions on how to wire this up. You'll probably also want to look at Providing Controller Content if you're not already familiar with that part.