NSCollectionView Delegate Method on Select Header - macos

The latest update to NSCollectionView allows the delegate to detect the selection of items with
- (NSSet<NSIndexPath *>*)collectionView:(NSCollectionView*)collectionView shouldSelectItemsAtIndexPaths:(NSSet<NSIndexPath*>*)indexPaths
and
- (void)collectionView:(NSCollectionView*)collectionView didSelectItemsAtIndexPaths:(NSSet<NSIndexPath*>*)indexPaths
, among others.
However, insofar as I can tell, these methods only detect the selection of NSCollectionViewItem objects, and not any present header or footer views.
Are there any delegate methods to detect the selection of the header and/or footer views? If not, what is the best way to implement this detection?

Indeed these delegate methods are only for selecting items. If you want to do something when the header of footer view is clicked, you can add a gesture recognizer to those views yourself and hook it up to an IBAction on your controller.

Related

Best practice for setting a data source and delegate for a UITableView

This question may not have a straight answer, but I am curious as to what others think. I have a UIViewController and inside that I have 2 objects a UIView and and UITableView. Each object as it's own custom class. My question is about the UITableView, what object should be the datasource and the delegate. Right now I have the UIViewController set to those rolls, but is it beset practice to set the object itself to be the data source and the delegate, maybe use the method awakeFromNib to set those 2 sources. Are both ways ok? I would think that setting the data and the delegate to the class that represents the tableview would keep that code apart from the view controller, which I would think would be a good thing.. but maybe not...
Good question actually.
Look at the Controller as an example of the Mediator Pattern from the Gang of Four: it's mediating the relationship between the View and the Model. Most of the web world has gone to using binding of some sort, so you typically see model objects 'bound' directly to the view layer, e.g. a text edit field might have an expression indicating which field in the domain object it is editing, then the framework will provide the services of marshaling and unmarshaling that data.
In Cocoa, you typically don't do that: you bind to properties in the Controller, and those typically are then used to transform the underlying domain class. So for instance, if you make a storyboard and make a form and have a custom controller, now you want to edit the name of some entity, e.g. User, you would CTRL-drag from the edit box over to the source, it would make an outlet, which would then give you control not only of what appears in that box, but the control itself. Then you could add a submit button and CTRL-drag to create a method, for Save, and when that's clicked, you could update the underlying User instance.

How to create a header view for NSCollectionView

I need to set a header view for my NSCollection view. When I researched I found that NSCollection view don't support a default header view like NSTableView. I need a header almost like the one used in skype. ie. apart from displaying just a title, I may need to perform some actions upon clicking header corresponding to a column. for eg. Sort by name upon clicking 'Name' column.
What is the best way to implement this if I subclass and create my own header view? Which view should I subClass to get both, the look and feel of NSTableview header and the clickable properties like that of NSButton?

methods which are invoked automatically when a tab is selected in cocoa

I have a tabview in which i have added 3 tabview Items.In each tab i have fields into which i want to populate data automatically. Which methods are invoked automatically when a tab is clicked.Please help me in this...
NSTabView allows you to specify an object as its delegate. This delegate object should be an instance of a class that conforms to the NSTabViewDelegate protocol. This protocol declares, amongst others methods,
-tabView:willSelectTabViewItem: to inform the delegate that a tab item is about to be selected;
-tabView:didSelectTabViewItem: to inform the delegate that a tab item has been selected.
You probably want to implement -tabView:willSelectTabViewItem: so that the fields are populated right before that tab item is selected.

Cocoa - Whats the best way for modifying NSOutlineView

Result should be an settings panel with an OutlineView and "add item", "add group" and "delete" buttons. The buttons add entries to an NSOutlineView. The data is stored in a NSMutableDictionary (or whatever is suitable). Sorting/DragDrop enabled for the OutlineView.
What is the best or most comfortable way for this (and write less code)?
Modifying NSMutableDictionary, NSOutlineView refreshes from NSMutableDictionary?
Modifying NSOutlineView, Result is stored in NSMutableDictionary?
... NSTreeController?
... CoreData?
What's best practice for that?
Thanks in advance!
This is a pretty broad question. You should always store your model data in a model object of some kind, be that a Core Data entity, an NSMutableDictionary or a custom object of your own creation. You should definitely NOT be storing the data in an NSTreeController or NSOutlineView instance, these are not model objects.
If you're using Core Data for the rest of your app and you need to persist the data that is manipulated by the outline view then this is a good choice, but it might be overkill if you have only simple requirements.
To control what is displayed in the outline view you can either use NSTreeController or your own controller object that responds to the NSOutlineView datasource and delegate protocols. In practice you might use both, as some things such as whether or not an item is a group item can only be controlled by the NSOutlineView delegate methods.
In my personal experience I've found that NSTreeController can be very difficult to deal with for anything beyond very simple tasks and I now longer use it, I find it's much simpler to just use the datasource methods in my own controller.
As far as modifying the contents of the outline view, you should always modify the model via a controller, you should never update the view directly. You would implement methods such as -add: in your controller or use the -add: method of NSTreeController if you're using it.
Your view's controller should then detect the change in the model and ask the view to update. The view controller and model controller can be the same object but they don't have to be. Key-Value Observing is a useful technology that can inform your controller of a change in the model.
Here's some sample code from Apple that you might find useful:
http://developer.apple.com/mac/library/samplecode/SourceView/
http://developer.apple.com/Mac/library/samplecode/AbstractTree/

Binding to a NSViewController's representedObject

(Abstract: bindings work in code, but not in IB)
I have a window managed by a NSWindowController. To the left of the window is a source view. To the right is a table view showing the elements of the currently selected source.
I have set up a NSTreeController within my window XIB. I want its contents to be used for the source view. It's selection will drive the table view.
I am trying to split this up using NSViewControllers. One view controller will load a NIB containing the source view. Another view controller will load the table view.
Seeing that I need access to the NSTreeController within the source view controller, I have set it to be the view controller's representedObject. (Actually for this setup to be done by the time awakeFromNib is called on the view controller, I have turned representedObject into an IBOutlet).
All works fine when I wire my source view up in code:
[outlineView bind:#"content"
toObject:sources
withKeyPath:#"arrangedObjects"
options:nil];
[outlineView bind:#"selectionIndexPaths"
toObject:sources
withKeyPath:#"selectionIndexPaths"
options:nil];
[[outlineView tableColumnWithIdentifier:#"Title"] bind:#"value"
toObject:sources
withKeyPath:#"arrangedObjects.title"
options:nil];
I am however unable to reproduce this using Interface Builder. Thing is, here the "controller key" textfield is grayed out. Thus I bind column's "value" to the file owner using a model keyPath of "representedObject.arrangedObjects.title". This does not show the desired behavior. Actually an exception is thrown: -[NSProxy doesNotRecognizeSelector:_mutatingNodes] called!
How can I use representedObject in IB?
Can I create a controller in IB which acts as proxy to representedObject?
Could I set-up a tree controller in the source view XIB which during NIB loading gets swapped out for the representedObject?
I moved away from using representedObject. It appears that is meant only for model objects.
I now pass in my tree controller using a custom outlet. I continued setting up and tearing down the bindings in code.
I’ve similar issues when I try to pass a reference to an object controller (NSTreeController in my case). I don’t think this is how Apple wants you to use their KVO-compatible controllers. The exceptions look like they’re XIB-unarchiving & timing-related.
The trick is not to pass the controllers, but to pass the underlying data and keep the selection in sync.
This way you can set up your bindings in a storyboard and won’t get any exceptions. You’ll have to set up a new instance of an object controller for every child view controller (copy & paste in Storyboard once you configured the first one works). For a detailed example take a look at another answer that gets much more into detail.

Resources