NSTableView rowViewAtRow: always returning nil - cocoa

I'm trying to display an NSPopover with additional information to a selected row of an NSTableView. For that I need to get a reference to the view representation of the selected row so I can "attach" my popover to it:
NSInteger row = [[self membersTableView] selectedRow];
NSTableRowView *aView = [[self membersTableView] rowViewAtRow: row makeIfNecessary: YES];
[self setQuickLookPopoverController: [QuickLookPopoverController showPopoverFor: anObject at: aView]];
In the above, the result of aView is always nil. According to Apple documentation, this is the method to obtain a view object, given a selected row. Especially the last sentence of the discussion is a bit weird:
Discussion This method will first attempt to return a currently
displayed view in the visible area. If there is no visible view, and
makeIfNecessary is YES, a prepared temporary view is returned. If
makeIfNecessary is NO, and the view is not visible, nil will be
returned.
In general, makeIfNecessary should be YES if you require a resulting
view, and NO if you only want to update properties on a view only if
it is available (generally this means it is visible).
An exception will be thrown if row is not within the numberOfRows. The
returned result should generally not be held onto for longer than the
current run loop cycle. It is better to call
rowViewAtRow:makeIfNecessary: whenever a view is required..
Why is this method always returning nil?

Solved it. I used NSTableView's method (NSRect) rectOfRow: (NSInteger) rowIndex which will give the frame of the required row.

Thanks for showing me the right direction, I had the same problem! I ended up doing the following, but note that I disabled selection of empty rows and that the following code is inside an IBAction:
[popOver showRelativeToRect:[sender bounds]
ofView:[sender rowViewAtRow:[sender selectedRow]
makeIfNecessary:YES]
preferredEdge:NSMaxXEdge];

Related

Can't change column width in response to outlineViewItemDidExpand

I want to update the column width to the width of the widest entry whenever a node in my NSOutlineView is expanded. Thus, my delegate listens to outlineViewItemDidExpand and calls
[column setWidth:maxColumnWidth];
in it. maxColumnWidth is the width of the widest entry.
However, for some reason, calling setWidth from inside outlineViewItemDidExpand doesn't seem to do anything. When I call it later, e.g. as a response to a button click, it works just fine, but from within outlineViewItemDidExpand it just does nothing.
So any idea what I could do to update the column width whenever the user clicks on an expander icon? Thanks a lot!
If autoresizesOutlineColumn is YES (default) then the outline view resizes the outline column after outlineViewItemDidExpand. Solution: set autoresizesOutlineColumn to NO.
I was able to solve this by calling setWidth() from a selector called by performSelector() from within outlineViewItemDidExpand, like so:
-(void) setColumnWidth
{
[theColumn setWidth:...];
}
-(void) outlineViewItemDidExpand:(NSNotification*)notification
{
// calling setWidth() here doesn't work
// [theColumn setWidth:...];
// but calling setWidth() from a selector works!
[self performSelector:#selector(setColumnWidth) withObject:nil afterDelay:0.0];
}
Don't ask me why calling setWidth() only works from within a selector but it actually does...

How to expand table view cell and show content beneath it?

I want to have the table view cell expand and show the buttons that I have laid out below the visible view when the cell isn't selected. So far I have managed to expand the cell so that the entire view shows with the buttons, but there is one major problem with this....
The buttons that are supposed to be revealed only when the cell is selected always appear in the table, and the table view looks really weird becuase for each cell there are buttons overlapping the next cell which were supposed to be hidden!
I have tired making a subclass of the cell, but I am stuck because when I override the setSelected method to show the button, all the buttons from all the cells show up, not just the one I clicked, Ill provide my code below.
I there an easier way to show the buttons without using a subclass? And if not how could I use the subclass in a way that wouldn't show all the buttons for all the cells?
Cell Subclass (.m file)
- (void)awakeFromNib {
// Initialization code
editHidden.hidden = YES;
removeHidden.hidden = YES;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
editHidden.hidden = NO;
removeHidden.hidden = NO;
// Configure the view for the selected state
}
Your table view delegate needs to implement tableView:heightForRowAtIndexPath:. Implement this method to return the correct height for your cell given the state that it is in (collapsed or expanded). When it comes time to expand your cell you should update your state and call [tableView beginUpdates]; [tableView endUpdates]; to have it recalculate and relayout the tableview.

WKInterfaceTable not updating after calling removeRowsAtIndexes

Maybe I'm doing something wrong but if I call removeRowsAtIndexes: on a WKInterfaceTable instance like so:
NSIndexSet *indexes = [[NSIndexSet alloc] initWithIndex:index];
[self.table removeRowsAtIndexes:indexes];
Should the table not update? Logging the numberOfRows reported by the table shows the number correctly reduced by 1, but on screen nothing changes.
Trying to select a row after this point can actually result in selecting the row below, so clearly the table has recorded the deletion but at least in the simulator it isn't showing.
Has anyone else expereinced this? Is this a bug or do I need to force the table to refresh somehow?
Your class must be fully loaded before you calling removeRows AtIndexes. (when watch interface is visible to user).
- (void)willActivate {
[super willActivate];
NSIndexSet *indexes = [NSIndexSet indexSetWithIndex:index];
[self.table removeRowsAtIndexes:indexes];
}
At what point did you call the method removeRowsAtIndexes in your code ?

Return position of selected row in NSOutlineView

I have an NSOutlineView which when a row in the outline view is double-clicked, an NSPopover is displayed using the following code:
-(void)doubleClick:(id)nid{
NSLog(#"Test double click");
[_popover showRelativeToRect:[nid bounds] ofView:nid preferredEdge:NSMaxXEdge];
}
The code works fine but places the popover in the middle of the vertical height of the outline view. I would like the popup to appear next to the row which is selected (double-clicked) in the outline view. Is there a call I can make to the Outline View to return the position of the selected row? I couldn't seem to find such a method in the documentation. Clearly I would replace [nid bounds] which such a call. Else, any other suggestions of how I could work around this would be appreciated.
Don't forget that NSOutlineView inherits from NSTableView. You're looking for -frameOfCellAtColumn:row:. The column is probably 0. The row you can obtain with -selectedRow.
If your outline view is view-based, you could also pass the row view (-rowViewAtRow:makeIfNecessary:) and NSZeroRect for the rect to -showRelativeToRect:..., so it automatically tracks the row.

Unable to get tab order working within NSPopover

I have a View within an NSPopover, and I am unable to set the tab order correctly. I have set the nextKeyView within my 4 text fields. But it tends to flip from TextField1 to Search1, instead of TextField1 -> TextField2. I have tried inserting [self.view.window makeFirstResponder:textField1] also [self.view.window setInitialFirstResponder:textField1] along with recalculatekeyviewloop but with no luck.
Any help would be much appreciated.
I had a similiar problem when composing the popover-view of certain subviews programatically in awakeFromNIB. I could solve the problem by inserting the subviews after the popover had its private NSPopoverWindow set (i.e. it was shown the first time). It seems like the popover is re-evaluating the view-loop when the popover-view is embedded in the private child-window - ignoring the view-loop given in the view.
You could try the following:
-(void) popoverDidShow:(NSNotification *)notification{ // NSPopoverDelegate-method
if (!popoverDidShowForTheFirstTime){
[self setUpViews];
}...
-(void) setUpViews{
popoverDidShowForTheFirstTime = YES;
// insert views and establish nextKeyViews ...

Resources