How to prevent a row of UITableView to deSelect? - objective-c

When i select a row of UITableView it becomes green(customized), but when i select another row, previously selected row do not stay green. I'm reloading my table after every row selection.I've tried this
NSIndexPath *selection = [mainTable indexPathForSelectedRow];
[mainTable selectRowAtIndexPath:selection animated:NO
scrollPosition:UITableViewScrollPositionNone];
but with this code i get only most recent selected row green(selected)
I've searched for this and found some suggestions, most of them suggest to store index value of selected row in an array and use this array later, i've tried this but it did not work.
Any other suggestion or sample code will be appreciated.

Update:
A better way to achieve this would be to return nil from the UITableViewDelegate method tableView:willDeselectRowAtIndexPath: for the indexPath that you wish to stay selected.
Don't use this :
Try this add UITableViewDelegate method:
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
//use this for row u want to prevent to deSelect
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}

Do this:
mainTable.allowsMultipleSelection = YES;
From the UITableView Class Reference:
allowsMultipleSelection
A Boolean value that determines whether users can select more than one row outside of editing mode.
#property(nonatomic) BOOL allowsMultipleSelection
Discussion
This property controls whether multiple rows can be selected simultaneously outside of editing mode. When the value of this property is 'YES', a check mark is placed next to each row that is tapped. Tapping the row again removes the check mark. If you call indexPathsForSelectedRows, you can get the index paths that identify the selected rows.
The default value of this property is NO.

Related

NSTableView Multiple Row Types

I'm trying to create a homework planner app that has two types of TableCellViews in a View Based NSTableView. One type is a narrow bar that just has a label of what subject the below homework is for, and the other type is a row to input homework items. (I'll include a screenshot below.)
My question is: when creating new rows in a TableView, how do you specify which type of row you'd like to create? I'm assuming it has something to do with identifiers, but I can't find any information on how to use them in this way.
This is basically how it would look:
You are on the right track with the identifiers. Here's how you use them.
First setup your NSTableView with your specific row types (as you've probably already done). In the screenshot below I made one row with a title and description and another with a few buttons.
Next, you need to setup the desired identifiers. Click the first row in Interface Builder and select the Identity Inspector. Pick a unique identifier for your first row. Do the same for the other(s).
Finally, in your implementation create a new row of a specific type using the following code:
TableViewController.m
#pragma mark - NSTableViewDelegate
- (NSView *)tableView:(NSTableView *)tableView
viewForTableColumn:(NSTableColumn *)tableColumn
row:(NSInteger)row {
NSTableCellView *cell;
if(someCondition == YES) {
cell = [self.tableView makeViewWithIdentifier:#"ButtonRow" owner:self];
} else {
cell = [self.tableView makeViewWithIdentifier:#"TitleDescriptionRow" owner:self];
}
return cell;
}
If you're looking for a more in depth tutorial, check out Cocoa Programming L51 - View-Based NSTableView (YouTube video, not by me).

How to dynamically create multiple UITableViews in one UIViewController

I'm new at developing with XCode and Objective-C and I hope you can help me.
The problem is, I have an UITableViewController with an UITableView (created with the InterfaceBuilder).
The cells under the section headers are expandable.
Now I want to dynamically create multiple UITableViews under the existing TableView.
The style will be the same like the existing TableView's style.
Could you tell me how it is possible to create these TableViews programmatically?
Thank you very much
Michael
From what you are saying try using a grouped table view. Check out this link for a quick overview, and go to the grouped table view section.
Edit found this example here:
Seems like it is what you are looking for. And a very cool idea also.
You'll have to just make your own custom header row and just put that as the first row of each section. Subclassing the UITableView or the headers that are on there now would probably be a huge pain and I'm not sure you can easily get actions out of them the way they work now. You could easily set up a cell to LOOK like a header, and setup the tableView:didSelectRowAtIndexPath to expand or collapse the section it is within manually.
If I were you I'd store an array of booleans corresponding the the "expended" value of each of your sections. You could then have the tableView:didSelectRowAtIndexPath on each of your custom header rows toggle this value and then reload that specific section.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
///it's the first row of any section so it would be your custom section header
///put in your code to toggle your boolean value here
mybooleans[indexPath.section] = !mybooleans[indexPath.section];
///reload this section
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
}
}
You'd then setup your number numberOfRowsInSection to check the mybooleans value and return either 1 if the section isn't expanded, or 1+ the number of items in the section if it is expanded.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (mybooleans[section]) {
///we want the number of people plus the header cell
return [self numberOfPeopleInGroup:section] + 1;
} else {
///we just want the header cell
return 1;
}
}
You would also have to update your cellForRowAtIndexPath to return a custom header cell for the first row in any section.

How can I show table view cell values after click button?

I have a table view and it is load from table view cells. But I want to see this table's values after click a button.
With this method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;,
I can see all data when view did load.
But firstly I dont want to see datas. I want to see thats after click a button. How can I do this?
Keep your table source equal to nil, then when the button is pressed set it to the list of values you need and reload the table view.
so ... if your table source is let's say the ivar NSArray* tableData, and the array with your values is the ivar NSArray* values then in your IBAction for your button you should do :
-(IBAction)buttonPressed:(id)sender
{
tableData = values; //load the values in the table source
[self.tableView reloadData]; //just call reloadData on the tableView
}
That's about it
Have a private BOOL property in your subclass of UITableViewController that keeps track of whether or not the button has been pressed. Then, in tableView:CellForRowAtIndexPath: load cells differently based on the value of that property. When the property is set, call [self.tableview reloadData] (capitalization might be wrong).

Change UITableView row height without dismissing keyboard

I have a TextView inside a UITableViewCell. The text inside the TextView can be edited right there in place.
The TextView grows and shrinks vertically depending on the number of lines the text contains. So far I haven't found a possibility to also let the row containing the TextView grow and shrink dynamically.
[tableView reloadData];
or
[tableView reloadRowsAtIndexPaths: withRowAnimation:];
don't work, because they dismiss the keyboard on every change.
Is there a way to change height of an individual row in a UITableView without dismissing keyboard?
Yes, you can have the row heights adjust as you type. It's not documented, and it defies reason, but all you need to do is set the new value in tableView.rowHeight (or have heightForRowAtIndexPath:ready to compute the new heights), then do this:
[tableView beginUpdates]; // updates the row heights ...
[tableView endUpdates]; // ... nothing needed in between
The task is to invoke row height recomputation without cell reuse (to save current responder).
One can call moveRowAtIndexPath:toIndexPath: for the same indexPath right after height change
- (void)textInputTableView:(UITableView *)tableView cellHeightDidChangeForIndexPath:(NSIndexPath *)indexPath
{
[tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
}
After reloadRowsAtIndexPaths the cell changes memory value, so if you call becomeFirstResponder just after the reloadRowsAtIndexPaths, you are trying to set as firstResponder the old cell, which does not exist (becomeFirstResponder returns false and keyboard exits).
The solution is to call again cellForRowAtIndexPath in order to get the new memory value of the reloaded cell, and then call becomeFirstResponder to that cell.

indexPath null in didSelectRowAtIndexPath in an ipad splitview navigation app

I'm porting a fairly simple iPhone Navigation based app to a Split View iPad app.
I have two nested levels of navigation on the Master view. The user picks a value from the first table and it loads the 2nd table. Selecting a value on the second table loads the Detail item for the detail view. Or it's supposed to. The didSelectRowAtIndexPath on my 2nd controller is firing but indexPath is null.
I'm following the SplitView template fairly closely. I'm only really getting off the beaten track by adding that 2nd TableViewController. My RootViewController loads the 2nd TableViewController on didSelectRowAtIndexPath, and that part's working. In my 2nd TableViewController.m I'm trying to set the detail item for the DetailView. But it's that didSelectRowAtIndexPath method that's not giving me the row. I'm fairly new to this, but it seems odd to me that the method for clicking a row would fire but not have the index for that row.
Here's the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TrackerSplitViewAppDelegate *appDelegate = (TrackerSplitViewAppDelegate *)[[UIApplication sharedApplication] delegate];
detailViewController.thisRequest = [appDelegate.requests objectAtIndex:indexPath.row];
NSLog(#"Request Loaded: %#", detailViewController.thisRequest.Title);
NSLog(#"Index Row: %#", indexPath.row);
[appDelegate release];
}
The array of requests is loading properly (appDelegate.requests) but my objectAtIndex is failing because indexPath is null. Or at least indexPath.row is null.
EDIT: Ok, the comments below are correct, I'm not using NSLog properly. The indexPath.row is fine (I thought it was also showing up as null using the mouseover in the debugger, but I just don't know how to use the debugger properly).
The detailViewController property isn't getting set right for some reason. If I substitute with this:
//detailViewController.thisRequest = [appDelegate.requests objectAtIndex:indexPath.row];
Request *aRequest = [appDelegate.requests objectAtIndex:indexPath.row];
The aRequest object loads just fine. So the next question is why setting my property on my detailViewController object isn't working. I'm still quite fuzzy on how things persist in this environment. Any additional input would be great.
The value of indexPath.row is not a string. You can't log it with %#. Try using %i or %li, which are used for integers. Also, you haven't reaLly properly checked for the request to be loaded, afaik. Is the title property only available after a successful load?
NSLog(#"Index Row: %#", indexPath.row);
indexPath is an NSIndexPath object, you could use %# to print it.
But indexPath.row and indexPath.section are NSUInteger. So you have to use %u to print them.
So maybe your indexpath.row is not nil (as in no object) but 0 (as in zero, the number before one)
Select a row that is not the first one and you should get a crash.