NSTableView IBOutlet clickedRow is always -1 - cocoa

I have a problem with getting the clickedRow set through IB.
Setup
In IB I have a view with custom class set, call it MyView. The file's owner of the XIB is MyVC.xib. In IB I have also created an NSTableView inside MyView.
Thus the view hierarchy is like so
MyView -> (auto-generated) NSScrollView -> NSClipView -> NSTableView.
The tableview is setup through bindings and connected the double-click action/target correctly, as mentioned in this post Double click an NSTableView row in Cocoa?
I have declared and connected an IBOutlet NSTableView in MyVC.h.
Problem
When the selector is called, the NSArray of objects are passed in nicely. However, I cannot know which of them to operate in since [_tableView clickedRow] always returns -1.

Related

How to set view outlet for a UITableViewController?

I created an empty xib, I dragged a UITableViewController, set Custom class to my class that extends from UITableViewController at both the UITableViewController and File's Owner.
When I run, it says:
'A view can only be associated with at most one view controller at a time! View ; layer = ; contentOffset: {0, 0}> is associated with . Clear this association before associating this view with .'
At connections inspector I see that the UITableViewController element has:
tableView - Table View
view - Table View (greyed)
dataSource - Table View
delegate - Table View
First Responder has nothing.
File's Owner has:
tableView is not attached to anything
view - Table View
If I remove the view connection at File's Owner, it claims that the view outlet is not set.
It is difficult to imagine what happens based on the information provided. However:
The error message says that you have a UIView, and you try at runtime to connect this UIView to two UIViewControllers, which is not possible.
If you just subclass a UITableViewController, without adding properties or implementing methods, then setup a UITableViewController in an empty storyboard, and set the class of this UITableViewController to your subclass, you have only a single UITableViewController, and you will not get this error.
So somewhere in your project you must instantiate a second UITableViewController programmatically, and set its UIView property (which is a UITableView) to the UIView of the other UITableViewController.
You should ensure that you have only a single UITableViewController, namely your custom subclass.
I guess the correct answer is DON'T drag UITableViewController to the interface builder. Have 2 IBOutlets connected, one for the view, one for the table. DO drag a UITableView instead.
Hope this helps other people.

How to connect outlet in a table cell view?

I am using a view-based table, and I want to create an outlet for an element in a cell view. I cannot get the outlet to connect though... it's always nil.
Specifically, I have a NSProgressIndicator in a table cell and want to manipulate it in code.
Here's what I have so far:
I have created a subclass of NSTableView, with the corresponding outlet property:
#interface MyTableCellView : NSTableCellView
#property IBOutlet NSProgressIndicator *myProgressIndicator;
#end
#implementation MyTableCellView
-(void)awakeFromNib
{
// _myProgressIndicator is nil!
}
#end
And I have set the custom class in the nib. The existing NSTableCellView is replaced with MyTableCellView via the dropdown.
At this point, some observations:
If I Ctrl+Click and drag the progress indicator to connect this outlet, it is not shown.
Likewise, if I try to Ctrl+Click and drag the progress indicator using the assistant editor, I can only connect to the property via binding. It doesn't recognize this as a valid outlet.
However this outlet IS shown on the sidebar, with a warning that it doesn't exist:
I know MyTableCellView is being used. Breakpoint on awakeFromNib confirms this, and confirms that _myProgressIndicator is nil.
This is a sandbox project, with barely more than what I've described.
SO, how do I access this progress indicator from code?
I don't believe you should do it that way; instead:
Modify the model object used by the table view's data source to populate the table view.
Call the table view reloadData (or better reloadDataForRowIndexes:columnIndexes:).
Therefore you should only need an outlet to the table view to do this and any modification of the table view's cell objects should be done within the table view delegate and/or data source methods.
As described in the question, the usual method to connect outlets in Interface Builder does not work (maybe it is fixed in a recent version of Xcode, I am still using a version earlier than 6). Anyhow, it does work via the Connections Inspector.
Create an IBOutlet in your subclass of NSTableCellView.
In your XIB, from Identity Inspector, change the NSTableCellView to your subclass.
From Connections Inspector, drag from your outlet to the View object.

Can't CTRL+Drag NSButton to custom NSView header

I'd like to create a custom NSTableCellView instantiated by Interface Builder. I've set my Table Cell View class to MyTableCellView, and properly created MyTableCellView : NSTableCellView .m/.h files.
However, I just can't CTRL+Drag a simple button from inside this view to MyTableCellView.h in order to create an IBOutlet.
Here is a video to show what happens: http://youtu.be/sNNbuVT-SZs.
How the view is subclassed:
How I try to CTRL+Drag a button
Also, sometimes, Interface Builder just don't allow the cell view's class to be modified. What's happening ?
I finally found a solution, that is a little weird but works as expected. Instead of connecting the NSButton to MyTableCellView header directly, I used the reversed path:
Manually create an outlet:
#property(retain, nonatomic) IBOutlet NSButton* button;
Then click the empty circle on the left, and drag it to your XIB file's button:
I have no idea why it works this way, please let me know if you know the anwser.

Can I use NSViewController to provide a reusable NSTableView with defined columns and data?

I'm fairly new to Xcode and Cocoa development, so please excuse me if I use the wrong terminology.
I have a window which has an NSTableView bound to a NSArrayController. The NSTableView has some predefined columns and the NSArrayController is populated with data when my window is loaded.
This all works fine, but I now need to re-use the functionality in a number of other windows.
After much reading I think and NSViewController is what I need, to provide an object that I can re-use in different windows in multiple .xib.
So what I have done is created a new NSViewController sub class in Xcode which also created a new xib for that controller.
The xib contains a custom view, where I have placed my NSTableView.
#interface KeyViewController : NSViewController
#property (weak) IBOutlet NSTableView *keyTable;
#end
The files owner class is set to the KeyViewController, and the view outlet is set to the files owner.
I then placed a ViewController object into the original window and hooked up the view to a new custom view in the window
I then set the nib name for the ViewController in its properties.
The new view never gets displayed and the view controller initWithNibName never gets called.
Am I missing something vital or missing the plot completely. Should you be able to do this just with interface builder or do I need to alloc and init the view in code?
If I do have to do it in code, whats the purpose of the ViewController object in IB and the Nib Name property for it?
Thanks..

Consise simple example of working with NSCollectionView drag and drop

I would like to figure out how to perform drag and drop from strings in a table view onto a collection view. I know there are delegate methods for collectionView drag and drop but can't find any examples of how to implement them. I have my collection view set up, it seems to be working correctly but don't know how to finish.
Any help is appreciated.
Update: The collection view setup I am working with has 3 NSTextFields and 2 check boxes for each collection item. There is also a tableView in the same view. The table view is passed an a MutableArray of strings. I want to be able to drag string values from the table view rows into the appropriate textFields in the collection view item.
This is different from the typical way drag and drop is used for collection views.
I am going to answer my own question because I spent quite a bit of time today trying to figure this out, Many people struggle with this procedure and mostly because I feel bad I keep asking the Stack community all these collection view questions all week:
I discovered the default behavior of the NSTextField actually allows a drop if it is in focus. The problem is that I need the appropriate NSTextField to auto focus on mouse enetered event. So as things turned out, I did not even need the NSCollectionView drag and drop delegates. I needed the NSTableView drag delegates and I needed to subclass the NSTextField and implement mouse event (drop) delegates in it.
so my class for the original collectionViewItem look like this:
//someClass.h
#interface SomeClass : NSObject{
IBOutlet NSTextField *field1_;
IBOutlet NSTextField *field2_;
IBOutlet NSTextField *field3_;
IBOutlet NSButton *chkBox1_;
IBOutlet NSButton *chkBox2_;
}
#porperty(readwrite, copy) NSTextField *filed1_;
properties are made for all 5 outlets for binding purposes. If you follow the tutorial on the Mac OSX Dev Library ; Collection View Programming Guide, it walks you through the process of setting up a collection View but it uses bindings.
So now the key is to set up a textField sub class
//MyNSTextField.h
#import
#interface MyNSTextField : NSTextField{
//mouse positioning
unsigned long last_;
}
//MyNSTextField.m
#import "MtTextField.h"
#implementation
-(void)dealloc{
[super dealloc];
}
-(void)awakeFromNib{
//register for dragged types
//any other nib stuff
}
//three required mouse events
-(unsigned long)draggingEntered:(id<NSDraggingInfo>)sender{
//this forces the textfield to focus before drop
[self.window makeFirstResponder: self];
NSPasebord *pBoard;
self->last_ = DragOperationNone;
pBoard = [sender draggingPastboard];
return self->last_;
}
-(unsigned long)draggingUpdated:(id<NSDraggingInfo>)sender{
return self->last_;
}
-(void)draggingExited:sender{
if([sender draggingSource] != self){
self->last = NSDragOperationNone;
}
}
}// end class
now just go back to the original class and change the name of your textField outlets from NSTextField to MyNSTextField and in the collection view, select each textfield and assign it the new class name in the inspector and as long as you had your tableview drag delegates set up, or if your are dragging from some other source, make sure you have the appropriate dragging source delegates set and it should work.

Resources