I have a UITableView with gets populated from a backing array every time cellForRowAtIndexPath is called. The user can either go Back (via the nav bar) or they must submit the tableview's dataset to a server. Our GUI team wants the interface designed with a 'Done' button as the last cell in the table row in order to submit the dataset. Right now, numberOfRowsInSection is returning [myArray count] and I could conceivably alter the backing array with a "ghost" record for the done button, or simply return [myArray count] + 1 and catch the mis-matched array count in cellForRowAtIndexPath. Both ways, however, seem like trouble down the road. What's the best way to implement this?
Either put the button in the footer for the tableview, or mess with the row count. I've used both methods, just depends how much that last cell needs to look like the rest of the rows (or not look like them, in the case of using the footer)
Related
Context:
I have an NSOutlineView that acts like a source list, but does not use the actual source list highlighting style. (Imagine the sidebar in the Finder.)
This outlineView has only two levels: 1) "groups" and 2) "subitems". There is no additional nesting --- again, just like the source list in the Finder.
What I Want:
The top-level "group" rows in my OutlineView are NSTableCellViews with a single NSTextField. I would like my users to be able to edit the text in this textField (to rename the group) WITHOUT allowing them to select the entire group row in the OutlineView.
So far, I've not found a way to do this. If I prevent selection of group rows in my delegate for the OutlineView, it is not possible to edit the textfield. When I allow selection of the group rows, then I can get the textfield to edit just like any other.
Short of subclassing things and handling mouse events myself, is there a simple way to do this? Must a row in an NSTableView always be selected before textFields in that row can be edited?
I think it will work to use a custom subclass of NSOutlineView in which you override -validateProposedFirstResponder:forEvent: to return true if the proposed first responder is in a group row. Return whatever super returns for any other proposed first responder.
You can determine which row the proposed first responder is in by calling -rowForView:.
See this blog post from the Apple engineer who wrote the view-based table view stuff.
I'm trying to build this application where the Column 'Package Name' is populated from Core data. The second column has NSButtonCell added in IB and the idea is each time a checkbox is selected I need to get the name of the corresponding zip file in the 'Package Name' column.
I tried something like this
- (void)tableViewSelectionDidChange:(NSNotification *)notification {
NSTableView * tableView = [notification object];
NSInteger rowIndex = [tableView selectedRow];
NSTableColumn *column = [tableView tableColumnWithIdentifier:#"package-name"];
NSCell *cell = [column dataCellForRow:rowIndex];
NSLog(#"Found Value %#",cell.stringValue);
}
But the Value I get each time is different and inconsistent. For example if I select the 6ht checkbox (as shown in the screenshot), I expect to see 4.zip getting printed, but I get something else. How do I fix this ?
Both my Package Name and Installation Status columns are sortable.
Thanks
Don't consult the cells of the table. Instead, go straight to the data source or, if you're using bindings, the array controller.
First, in NSCell-based table views, there's typically a single cell object for the whole column. It is reused. It is configured for the first row and asked to draw in the appropriate location for that row. Then, it's configured for the second row and asked to draw in the appropriate location for the second row. Etc. So, retrieving the cell does not give you data for any particular row. The cell will have whatever properties it had the last time it was configured for a row, which may have been a completely different row than you're interested in.
(You could work around this by asking for the prepared cell for a row, using -[NSTableView preparedCellAtColumn:row:]. But that's really the roundabout way of doing things. The table view will just have to consult the data source in order to prepare the cell.)
If you're using an array controller, then your window/view controller should have an outlet to the array controller. Then, you can get the appropriate model object for a given row by calling:
object = [self.arrayController.arrangedObjects objectAtIndex:row];
If you're interested in the selected objects and your bindings are set up properly, you can just get the selected model object(s) directly from the array controller:
object = self.arrayController.selectedObjects[0];
Or:
for (object in self.arrayController.selectedObjects)
{
// ...
}
Note, though, that checking the checkbox in the second column is a distinct thing from selecting a row. Depending on how the table is configured, the user may be able to do either without the other. For example, they could select a row by clicking in the first column, which would not check the checkbox in the other column. They could also change the selection with the keyboard (e.g. down arrow).
I'm trying to programmatically select cells in a UICollection view. I'm new to Obj-C and I'm not quite sure how to use the selectItemAtIndexPath property. I can grab an array of the images the user has previously selected. It is just an array of numbers corresponding to named images. But I'm not sure how to use that information with selectItemAtIndexPath.
I've looked for examples of someone using
- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition
But I'm not sure how to use it with my UICollectionView so I can have the right cells selected when the view loads and thus be highlighted. I have multiple selection on.
You should call selectItemAtIndexPath: for each cell you want to highlight, like so:
[self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone]
Note that for one item (and one only!) you probably want to set the animated property to YES and provide a scroll position (one item only because otherwise you're going to be making a lot of needless animation calls).
You'll first need to get the index paths of the cells you want to select. The index path consists of two numbers: the section the cell is in and the row number (or order, if your collection view doesn't have rows) of the cell inside that section.
If you store the index paths of the cells the user has selected in an array then you can just iterate through. Otherwise you'll need to find the index path out, using a UICollectionView method such as indexPathForCell.
I am using a custom tableviewcell in one of my view's. I have decided to add a UISwitch to this cell to enable the user to delete multiple row's at once.
Normally when the user selects a row and taps my delete button I have a UIAlert pop up for confirmation and after that the alert clickedButtonAtIndex method handles the outcome. In that method I get the indexpath ( [self.myTableView indexPathForSelectedRow] ) and delete (or not) accordingly.
So basically as the title states instead of using the indexPath to fall into my delete statement, I need to check to see if self.myTableView.myCell.mySwitch.on is TRUE. Can anyone point me in the right direction for doing this? I will need to iterate through all rows in the tableview and for each row where the state is on it needs to be removed.
Thanks.
you should iterate through your cells using a nested loop ( or a single loop if you have only one section) and cellForRowAtIndexPath:.if you see a cell's switch.on = TRUE save it's indexPath in an array by calling indexPathForCell:. after you're done iterating through your cells, call deleteRowsAtIndexPaths:withRowAnimation: with the array previously created.
The requirement is something like this,
-- Similar to pList , there would be an + button, when user select this, it should make the last row editable,
Any idea how its feasible, i am able to get which row is selected, but not able to proceed further.
Just set the row to be editable via the provided methods.
NSCell *lastCell; // Find last cell
[lastCell setEditable: YES];