I am currently developing an app for iPhone and i have a spent time looking at how to select multiple rows in a table view however the answers i found did not include groups. I have a table as seen below with two groups one for client selection and the other for navigation links i would like to display the selected item for both groups rather than the entire table but i have had no luck finding any answers for this.
i understand you check can what section the row is in but i am not sure how to implement this. Any suggestions would be greatly appreciated. Additionally i do know how to select rows by changing the cell style depending on if it has been selected or not but its doing this for two groups im stuck on. Again thank you for any help.
This is the code to allow for multiple selection:
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.allowsMultipleSelection = YES;
}
Perhaps you are looking for something like this to execute code based on which section the selection is in:
#define CLIENT_SECTION 0
#define MENU_SECTION 1
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == CLIENT_SECTION) {
// execute code
} else if (indexPath.section == MENU_SECTION) {
// execute code
}
}
-(void)viewDidLoad{
[myTable setMultipleTouchEnabled:YES];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.section == 0)
{
[[myTable cellForRowAtIndexPath:indexPath.row] setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[[myTable cellForRowAtIndexPath:indexPath.row] setAccessoryType:UITableViewCellAccessoryCheckmark];
}
}
Related
It's really odd. :(
I am trying to implement swipe to delete in tableview. For this below is what I have.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"commitEditingStyle===%#", editingStyle);
if (editingStyle == UITableViewCellEditingStyleDelete) {
//add code here for when you hit delete
NSLog(#"now delete this cell");
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
Still when I swipe, swipe is done, but I can't see Delete button.
Any idea what is going on?
Edit 1
Something more weird now.
When I say mainTableView.editing = YES; in viewDidLoad, I have below.
Why delete option is appearing on the left side?
Also with editing option, still it appear same as first image.
Edit 2
// table view delegates
- (int)numberOfSectionsInTableView:(UITableView *) tableView {
return 1;
}
- (int) tableView:(UITableView *) tableView numberOfRowsInSection:(NSInteger)section {
return actualProductsArray.count;
}
-(UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
// created label and added into cell...
cell.backgroundColor = [UIColor clearColor];
cell.contentView.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Though this is not real answer, but below was error.
While defining size of tableview, I had defined its width as 1080 against 320 and hence I was not able to see delete button as it was way ahead of screen.
I had the same problem and it wasn't related to the width of the table or not having canEditRowAtIndexPath. I noticed the right nav bar button (Edit) would flash when I swiped left. The bug I found in my code was that I was calling tableView.reloadData() inside the setEditing method.
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
tableView.reloadData()
}
When I deleted the tableView.reloadData() line, the Delete button showed up just as expected. The reason I was doing the reloadData was because in Edit mode, I added an Insert line at the bottom of the table with an editingStyleForRowAtIndexPath = .Insert
You have to try Tableview.editing=YES in ViewDidload
I am only using the below line for swipe to delete in my code it works perfectly fine for me.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source
//[self.tblinboxmsg deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
Hope it helps you too...
I think you add the label directly on cell and not on cell.contentView.
If you provide the code here
// created label and added into cell...
We can help you more.
tableView.editing = true
has the behaviour like you have on image Edit 1. (Buttons are on left side)
But the buttons are on content, which should not. Because you are adding labels on cell directly
please add the labels in contentView and try again
I know this has been solved for over a year now but for some people that might encounter this problem, This might be just a constraint issue.That is how I solved mine.
Can't believe I've been trying to solve this problem for days, literally!, because I thought it was somewhere in my code implementation because I transitioned from UITableViewController to UITableView on a UIViewController. I just copied the UITableViewCell from the original UITableViewController and the code works well from the original UITableViewController implementation.
#Fahim Parkar first screenshot is pretty much the same scenario as mine. Slide and not showing delete. I think this means that canEditRowAtIndexPath is already implemented. His answer I believed is set in code but it led me to try out to check my constraints and finally fixed it
Currently I have an array of objects right now
- (void)viewDidLoad
{
[super viewDidLoad];
self.webSites = [NSMutableArray arrayWithObjects:#"Website", #"iOS", #"Android", nil];
}
I am trying to access the one at index:0 which should be Website with the following code to perform a segue to another table view controller where there will be categories to select from.
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
[self performSegueWithIdentifier:#"viewCategories" sender:nil];
}
}
Every time I run the app I click on Website and nothing happens, but when I click on iOS the segue performs. Any answer as to why I'm running into this problem?
You are using wrong method.
didDeselectRowAtIndexPath // Used for deselecting the cell row
should be
didSelectRowAtIndexPath // Used for selecting the cell row
I am working on an app where I need to reorder rows of section 1. I could achieve the reorder by implementing the tableView delegates. When the table is in editing mode I show reorder for section 1 and no controls for rest sections, but the rows of rest section should be deleted by swipe to left.
I am not sure whether this is possible but my requirement is exact the same.
Work done by me:
Below are the delegates of tableView I implemented:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.myTable isEditing]) {
return UITableViewCellAccessoryNone;
}
return UITableViewCellEditingStyleDelete;
}
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return YES;
}
return NO;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
The above code made the edit mode look as I wanted. Re-order sign got visible for only section 1 & red delete button is also not visible for rest sections (as desired).
Problem:
The rows of sections apart from section 1 were also not being deleted.When I swipe to left nothing happens.
In short in edit mode, section 1 should be re-order enabled and rest sections should work as they work in normal mode i.e swipe left to delete row should be functioning in tableview edit mode.
AFAIK you cannot achieve what you are trying. The two sections are part of the same table which is being edited. So once the table is in editing mode, it will affect all the sections and rows.
what you can do is divide the data in the two sections into two separate tables and load the tables in the header view of each section like this
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 0;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 0) {
TableViewController1 *tab1 = [[TableViewController1 alloc] initWithStyle:UITableViewStylePlain];
return tab1.tableView;
} else{
TableViewController2 *tab2 = [[TableViewController2 alloc] initWithStyle:UITableViewStylePlain];
return tab2.tableView;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return self.parentTable.frame.size.height/2;
}
tab1 will have data from first section and similar case for tab2 (forgive the variable naming). The parent table should have grouped style and also scrolling should be disabled for it. This way the two sections can be edited independent of each other. Also, this categorises data and each section becomes independently scrollable. Hope this helps and answers what ur looking for.
I have a UITableViewController that has 5 different sections, & each section contains an individual cell. In section 1 I have a UISegmentedControlthat offers two options by default segment 1 is picked so the rest of the sections (the other 4) correspond with segment 1. However, the problem that I am having is: Having the ability to switch to another UITableView that has other sections & cells that would correspond to segment 2, when of course segment 2 is selected in the UISegmentedControl
I am using storyboards for this project.
I know that the question of how to achieve this has been asked a thousand times, and I know how to do this if I was working with regular view controllers, I am new to working with UITableViewController and this is really giving me a hard time.
Things that I have tried:
No.1: I tried deleting the UITableViewController all together and replacing with a normal ViewController and sub a UITableView to the main view. The problem with that is that I was given an error by xcode because static cells require a UITableViewController to work, (unfortunately I am working with static cells).
No.2: I have tried to hide the cells with a conditional from the UISegmentedControl to only display the appropriate cells with the appropriate selection, but this did not work because I was not able to add my other sections & cells on top (as I would have normally done with regular UIViewController.
This is the code that I used to try method # 2 :
- (IBAction)segmentedControl:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
if (selectedSegment == 0)
{
upick= 0;
self.lengthCell.hidden=NO;
self.widthCell.hidden=NO;
self.depthCell.hidden=NO;
self.flowCell.hidden=YES;
}
else if (selectedSegment == 1)
{
upick =1;
self.lengthCell.hidden=YES;
self.widthCell.hidden=YES;
self.depthCell.hidden=YES;
self.flowCell.hidden=NO;
}
}
No.3: Countless hours of research on the net but can't seem to find the exact results I am looking for, most show how to do this with a UIViewController and the steps are different for this particular case.
I would really appreciate some advice & overall direction to take from here because I am stuck. Thanks guys!
Have all the cells you need available in your table view controller.
In your table view's datasource methods (i.e. numberOfSections, numberOfRowsInSection, cellForRowAtIndexPath) you can set all the correct numbers and data for the two states.
When the segmented control changes, you can do two things. Either you simply reloadData, as was suggested before, but then you do not get any animations. Or you use insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: to get the animation effect.
E.g. showing sections 1-2 in case 1 and sections 3-6 in case 2 (section 0 being the top section); each section has 2 rows
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return _control.selectedSegmentIndex == 0 ? 3 : 4;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return section == 0 ? 1 : 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// .. the usual boilerplate
if (_control.selectedSegmentIndex == 0) { /* configure cell */ }
else { /*do the same for the other case */ }
return cell;
}
-(void)segmentedControlDidChange:(UISegmentedControl*)sender {
NSIndexSet *indexes;
[_tableView beginUpdates];
if (sender.selectedSegmentIndex == 0) {
indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1,4)];
[_tableView deleteSections:indexes
withRowAnimation: UITableViewRowAnimationFade];
indexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1,2)];
[_tableView insertSections:indexes
withRowAnimation: UITableViewRowAnimationFade];
[_tableView reloadSections:indexes
withRowAnimation: UITableViewRowAnimationNone];
}
else {
// do the reverse
}
[_tableView endUpdates];
}
If I am correct, you need to switch between 2 table views using UISegmentedControl. You can use UIViewController and add 2 UITableViews to it and keep your UISegmentedControl outside the table views. Then may be you can manage it in the following method:
- (IBAction)segmentedControl:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *) sender;
NSInteger selectedSegment = segmentedControl.selectedSegmentIndex;
if (selectedSegment == 0)
{
//show Table1 and hide Table2
// Reload Table1
}
else if (selectedSegment == 1)
{
//show Table2 and hide Table1
// Reload Table2
}
}
Hope this helps.
I have a query; I have a dynamically populated table which contains strings. It has a search function attached, how can I perform a segue depending on the selected string/cell?
Any help would be much appreciated! Thanks!
I had a similar problem some time ago and this piece of code really helped me out.
I am assuming that you have your search function fully functional.
It is all based around an else if statement.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellcontent = selectedCell.textLabel.text;
if ([cellcontent isEqualToString:"CellOne"]) [self performSegueWithIdentifier:#"CellOne" sender:self];
else if ([cellcontent isEqualToString:"CellTwo"]) [self performSegueWithIdentifier:#"CellTwo" sender:self];
}
}
You will probably notice that this only caters for segues from the search RESULTS table. You need a very similar piece of code for your none-results table. I'm sure you can figure that little change out.
Let me know if you need any further information.
Implement the appropriate delegate method and assert the cell's textLabel text. Perform the appropriate segue...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if ([cell.textLabel.text isEqualToString:#"SomeText"]) {
[self performSegueWithIdentifier:#"MySegue" sender:cell];
}
}