indiaxxo
indiaxxo

Reputation: 245

UITableView select a row per section

I would like to make a selection like this enter image description here

How can I change my

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath  

delegate method to work in accordance with my requirement.

Upvotes: 1

Views: 4290

Answers (7)

C6Silver
C6Silver

Reputation: 3357

LimeRed has a great answer elsewhere in this thread, but it is not complete. The key issue is that the OP needs to have the accessory checkmark removed. Simply calling deselectRow will not remove the checkmark. Per the documentation, deselectRow does not call the delegate method tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) where the removal of the checkmark code might be located. Therefore you need handle this removal as part of the code that LimeRed wrote.

Here is a more complete implementation that removes the accessory checkmark again based on LimeRed's solution:

    func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
    {
        for path in tableView.indexPathsForSelectedRows ?? []
        {
            if path.section == indexPath.section && path.item != indexPath.item
            {
                let cell = tableView.cellForRow(at: path)
                cell?.accessoryType = UITableViewCellAccessoryType.none
                tableView.deselectRow(at: path, animated: false)
            }
        }

        return indexPath
    }

Upvotes: 2

LimeRed
LimeRed

Reputation: 1306

Why so complicated? Just deselect all cells of the same section before the user selects a new one.

First allow multiple selection for your UITableView. Then implement this delegate method:

Swift 3 version:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
{
    for vcip in tableView.indexPathsForSelectedRows ?? [] {
        if vcip.section == indexPath.section && vcip.item != indexPath.item {
            tableView.deselectRow(at: vcip, animated: false)
        }
    }
    return indexPath
}

Upvotes: 3

indiaxxo
indiaxxo

Reputation: 245

After a lot of modifications I have arrived with this

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{    
    UITableViewCell *cell = [aTableView cellForRowAtIndexPath:indexPath];


if(indexPath.section == 0)
{
    if([section1Rows count] == 0)
    {
        [section1Rows addObject:[NSNumber numberWithInt:indexPath.row]];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }

    else
    {
        [section1Rows removeObjectAtIndex:0];

        for (UITableViewCell *cell in [tabview visibleCells]) {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }

        [section1Rows addObject:[NSNumber numberWithInt:indexPath.row]];
        NSLog(@"%@",section1Rows);
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
}

if(indexPath.section == 1)
{
    if([section2Rows count] == 0)
    {
        [section2Rows addObject:[NSNumber numberWithInt:indexPath.row]];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }

    else
    {
        [section2Rows removeObjectAtIndex:0];

        for (UITableViewCell *cell in [tabview visibleCells]) {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }

        [section2Rows addObject:[NSNumber numberWithInt:indexPath.row]];
        NSLog(@"%@",section2Rows);
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
}

if(indexPath.section == 2)
{
    if([section3Rows count] == 0)
    {
        [section3Rows addObject:[NSNumber numberWithInt:indexPath.row]];
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }

    else
    {
        [section3Rows removeObjectAtIndex:0];

        for (UITableViewCell *cell in [tabview visibleCells]) {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }

        [section3Rows addObject:[NSNumber numberWithInt:indexPath.row]];
        NSLog(@"%@",section3Rows);
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
}


}

I'll explain the problem in steps, I have selected a row in 3 sections, If I select a row again in any of the sections... then everything goes haywire. How can I deselect the previously selected row and highlight the then selected row?

Thanks.

Upvotes: 0

indiaxxo
indiaxxo

Reputation: 245

This one's gonna be ViewController.h

@interface ViewController : UITableViewController
{
    NSMutableArray *list;
    NSMutableArray *sectionList;

    NSIndexPath *oldIndexPath0;
    int row0;
    NSIndexPath *oldIndexPath1;
    int row1;
    NSIndexPath *oldIndexPath2;
    int row2;
    NSIndexPath *oldIndexPath3;
    int row3;

    NSString *othersString;
    NSString *timeString;
    NSString *pRoomString;
    NSString *parkingString;
    NSString *smokingString;

    NSString *select0;
    NSString *select1;
    NSString *select2;
    NSString *select3;
}
@end

This one's ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewWillAppear:(BOOL)animated
{
    // initial row by 100;
    row0 = 100;
    row1 = 100;
    row2 = 100;
    row3 = 100;

    // initial strings by @”"
    othersString = [NSString stringWithFormat:@""];
    timeString = [NSString stringWithFormat:@""];
    pRoomString = [NSString stringWithFormat:@""];
    parkingString = [NSString stringWithFormat:@""];
    smokingString = [NSString stringWithFormat:@""];

    select0 = @"";
    select1 = @"";
    select2 = @"";
    select3 = @"";

    // Get row index
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp/rowString.txt"];
    NSData *rowData = [fileManager  contentsAtPath:fileName];
    // From NSData to NSString
    NSString *rowString = [[NSString alloc] initWithData:rowData encoding:NSUTF8StringEncoding];
    if (rowString) {
        // spit row string
        NSArray *rowArray = [rowString componentsSeparatedByString:@":"];
        for (int i=0; i<[rowArray count]; i++) {
            NSString *indexVal = [rowArray objectAtIndex:i];
            if ([indexVal length] != 0) {
                // set row value
                if (i == 0) {
                    NSString *row0Str = [rowArray objectAtIndex:0];
                    row0 = [row0Str intValue];
                }
                if (i == 1) {
                    NSString *row1Str = [rowArray objectAtIndex:1];
                    row1 = [row1Str intValue];
                }
                if (i == 2) {
                    NSString *row2Str = [rowArray objectAtIndex:2];
                    row2 = [row2Str intValue];
                }
                if (i == 3) {
                    NSString *row3Str = [rowArray objectAtIndex:3];
                    row3 = [row3Str intValue];
                }
            }
        }
    }
    // Update the view with current data before it is displayed.
    [super viewWillAppear:animated];

    //Initialize the array.
    list = [[NSMutableArray alloc] initWithCapacity:0];
    sectionList = [[NSMutableArray alloc] initWithCapacity:0];

    // section header
    NSArray *sectionHeaderArray = [NSArray arrayWithObjects:@"01",@"02",@"03",@"04", nil];
    NSDictionary *sectionHeaderDic = [NSDictionary dictionaryWithObject:sectionHeaderArray forKey:@"section"];
    [sectionList addObject:sectionHeaderDic];
    // time list
    NSArray *timeArray = [NSArray arrayWithObjects:@"time 01",@"time 01",@"time 01", nil];
    NSDictionary *timeDic = [NSDictionary dictionaryWithObject:timeArray forKey:@"time"];
    // private room
    NSArray *pRoomArray = [NSArray arrayWithObjects:@"room 01",@"room 02", nil];
    NSDictionary *pRoomDic = [NSDictionary dictionaryWithObject:pRoomArray forKey:@"pRoom"];
    // parking
    NSArray *parkingArray = [NSArray arrayWithObjects:@"park 01",@"park 02",@"park 03", nil];
    NSDictionary *parkingDic = [NSDictionary dictionaryWithObject:parkingArray forKey:@"parking"];
    // smoking
    NSArray *smokingArray = [NSArray arrayWithObjects:@"smoke 01",@"smoke 02",@"smoke 03", nil];
    NSDictionary *smokingDic = [NSDictionary dictionaryWithObject:smokingArray forKey:@"smoking"];
    // add all dictionary to list
    [list addObject:timeDic];
    [list addObject:pRoomDic];
    [list addObject:parkingDic];
    [list addObject:smokingDic];
    // Scroll the table view to the top before it appears
    [self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    //Number of section
    return [list count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    //Get the dictionary object
    NSDictionary *dictionary = [list objectAtIndex:section];
    NSArray *array;
    switch (section) {
        case 0:
            // time array
            array = [dictionary objectForKey:@"time"];
            break;
        case 1:
            // pRoom array
            array = [dictionary objectForKey:@"pRoom"];
            break;
        case 2:
            // parking array
            array = [dictionary objectForKey:@"parking"];
            break;
        case 3:
            // smoking array
            array = [dictionary objectForKey:@"smoking"];
            break;
        default:
            break;
    }
    //Number of rows
    return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Budget";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
        UITableViewCellStyleSubtitle;
    }
    //Get the dictionary object
    NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
    NSArray *array;
    switch (indexPath.section) {
        case 0:
            // time array
            array = [dictionary objectForKey:@"time"];
            if (indexPath.row == row0 ) {
                cell.accessoryType=UITableViewCellAccessoryCheckmark;
            }else{
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
            break;
        case 1:
            // pRoom array
            array = [dictionary objectForKey:@"pRoom"];
            if (indexPath.row == row1) {
                cell.accessoryType=UITableViewCellAccessoryCheckmark;
            }else{
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
            break;
        case 2:
            // parking array
            array = [dictionary objectForKey:@"parking"];
            if (indexPath.row == row2) {
                cell.accessoryType=UITableViewCellAccessoryCheckmark;
            }else{
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
            break;
        case 3:
            // smoking array
            array = [dictionary objectForKey:@"smoking"];
            if (indexPath.row == row3) {
                cell.accessoryType=UITableViewCellAccessoryCheckmark;
            }else{
                cell.accessoryType = UITableViewCellAccessoryNone;
            }
            break;
        default:
            break;
    }
    cell.textLabel.text = [array objectAtIndex:indexPath.row];
    NSLog(@"index cell");
    return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSString *title = nil;
    //Get the dictionary object
    NSDictionary *dictionary = [sectionList objectAtIndex:0];
    NSArray *array = [dictionary objectForKey:@"section"];
    title = [array objectAtIndex:section];
    return title;
}

#pragma mark -
#pragma mark Table view selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
    switch(indexPath.section)
    {
        case 0:
        {
            UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
            if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                cell1.accessoryType = UITableViewCellAccessoryNone;
                row0 = 100;
                timeString = @"";
            }else {
                NSIndexPath *SIndexPath0 = [NSIndexPath indexPathForRow:row0 inSection:0];
                if ([[tableView cellForRowAtIndexPath:SIndexPath0 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                    [[tableView cellForRowAtIndexPath:SIndexPath0] setAccessoryType:UITableViewCellAccessoryNone];
                }
                if (oldIndexPath0 == nil) {
                    oldIndexPath0 = indexPath;
                }
                UITableViewCell *cell2 = nil;
                if (oldIndexPath0 != indexPath) {
                    cell2 = [tableView cellForRowAtIndexPath:oldIndexPath0];
                }
                cell1.accessoryType = UITableViewCellAccessoryCheckmark;
                if (cell2) {
                    cell2.accessoryType = UITableViewCellAccessoryNone;
                }
                //Get the dictionary object
                NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
                NSArray *array = [dictionary objectForKey:@"time"];
                timeString = [array objectAtIndex:indexPath.row];
                row0 = indexPath.row;
                oldIndexPath0 = nil;
            }
            select0 = @"marked";
            break;
        }
        case 1:
        {
            UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
            if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                cell1.accessoryType = UITableViewCellAccessoryNone;
                row1 = 100;
                pRoomString = @"";
            }else {
                NSIndexPath *SIndexPath1 = [NSIndexPath indexPathForRow:row1 inSection:1];
                if ([[tableView cellForRowAtIndexPath:SIndexPath1 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                    [[tableView cellForRowAtIndexPath:SIndexPath1] setAccessoryType:UITableViewCellAccessoryNone];
                }
                if (oldIndexPath1 == nil) {
                    oldIndexPath1 = indexPath;
                }
                UITableViewCell *cell2 = nil;
                if (oldIndexPath1 != indexPath) {
                    cell2 = [tableView cellForRowAtIndexPath:oldIndexPath1];
                }
                cell1.accessoryType = UITableViewCellAccessoryCheckmark;
                if (cell2) {
                    cell2.accessoryType = UITableViewCellAccessoryNone;
                }
                //Get the dictionary object
                NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
                NSArray *array = [dictionary objectForKey:@"pRoom"];
                pRoomString = [array objectAtIndex:indexPath.row];
                row1 = indexPath.row;
                oldIndexPath1 = nil;
            }
            select1 = @"marked";
            break;
        }
        case 2:
        {
            UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
            if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                cell1.accessoryType = UITableViewCellAccessoryNone;
                row2 = 100;
                parkingString = @"";
            }else {
                NSIndexPath *SIndexPath2 = [NSIndexPath indexPathForRow:row2 inSection:2];
                if ([[tableView cellForRowAtIndexPath:SIndexPath2 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                    [[tableView cellForRowAtIndexPath:SIndexPath2] setAccessoryType:UITableViewCellAccessoryNone];
                }
                if (oldIndexPath2 == nil) {
                    oldIndexPath2 = indexPath;
                }
                UITableViewCell *cell2 = nil;
                if (oldIndexPath2 != indexPath) {
                    cell2 = [tableView cellForRowAtIndexPath:oldIndexPath2];
                }
                cell1.accessoryType = UITableViewCellAccessoryCheckmark;
                if (cell2) {
                    cell2.accessoryType = UITableViewCellAccessoryNone;
                }
                //Get the dictionary object
                NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
                NSArray *array = [dictionary objectForKey:@"parking"];
                parkingString = [array objectAtIndex:indexPath.row];
                row2 = indexPath.row;
                oldIndexPath2 = nil;
            }
            select2 = @"marked";
            break;
        }
        case 3:
        {
            UITableViewCell *cell1 = [tableView cellForRowAtIndexPath:indexPath];
            if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                cell1.accessoryType = UITableViewCellAccessoryNone;
                row3 = 100;
                smokingString = @"";
            }else {
                NSIndexPath *SIndexPath3 = [NSIndexPath indexPathForRow:row3 inSection:3];
                if ([[tableView cellForRowAtIndexPath:SIndexPath3 ] accessoryType] == UITableViewCellAccessoryCheckmark) {
                    [[tableView cellForRowAtIndexPath:SIndexPath3] setAccessoryType:UITableViewCellAccessoryNone];
                }
                if (oldIndexPath3 == nil) {
                    oldIndexPath3 = indexPath;
                }
                UITableViewCell *cell2 = nil;
                if (oldIndexPath3 != indexPath) {
                    cell2 = [tableView cellForRowAtIndexPath:oldIndexPath3];
                }
                cell1.accessoryType = UITableViewCellAccessoryCheckmark;
                if (cell2) {
                    cell2.accessoryType = UITableViewCellAccessoryNone;
                }
                //Get the dictionary object
                NSDictionary *dictionary = [list objectAtIndex:indexPath.section];
                NSArray *array = [dictionary objectForKey:@"smoking"];
                smokingString = [array objectAtIndex:indexPath.row];
                row3 = indexPath.row;
                oldIndexPath3 = nil;
            }
            select3 = @"marked";
            break;
        }
        default:
            break;
    }
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    // Cancle button and add an event handler
    self.navigationItem.leftBarButtonItem =
    [[UIBarButtonItem alloc] initWithTitle:@"Cancle"
                                     style:UIBarButtonSystemItemCancel
                                    target:self
                                    action:@selector(handleCancle:)];
    // Cancle button and add an event handler
    self.navigationItem.rightBarButtonItem =
    [[UIBarButtonItem alloc] initWithTitle:@"Use"
                                     style:UIBarButtonItemStyleBordered
                                    target:self
                                    action:@selector(handleUse:)];
}
- (void) handleCancle:(id)sender
{
    // pop the controller
    [self.navigationController popViewControllerAnimated:YES];
}
- (void) handleUse:(id)sender{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *fileName;
    // Get row index value
    fileName = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp/othersString.txt"];
    NSData *rowValData = [fileManager   contentsAtPath:fileName];
    // From NSData to NSString
    NSString *rowValString = [[NSString alloc] initWithData:rowValData encoding:NSUTF8StringEncoding];
    NSString *oldTimeString = @"";
    NSString *oldpRoomString = @"";
    NSString *oldParkingString = @"";
    NSString *oldSmokingString = @"";
    if (rowValString) {
        // spit row string
        NSArray *rowValArray = [rowValString componentsSeparatedByString:@":"];
        for (int i=0; i<[rowValArray count]; i++) {
            if ([rowValArray objectAtIndex:i] != @"") {
                // set row value
                if (i == 0 ) {
                    oldTimeString = [rowValArray objectAtIndex:0];
                }
                if (i == 1 ) {
                    oldpRoomString = [rowValArray objectAtIndex:1];
                }
                if (i == 2 ) {
                    oldParkingString = [rowValArray objectAtIndex:2];
                }
                if (i == 3) {
                    oldSmokingString = [rowValArray objectAtIndex:3];
                }
            }
        }
    }
    if (select0 == @"") {
        timeString = oldTimeString;
    }
    if (select1 == @"") {
        pRoomString = oldpRoomString;
    }
    if (select2 == @"") {
        parkingString = oldParkingString;
    }
    if (select3 == @"") {
        smokingString = oldSmokingString;
    }
    // make othersString string
    othersString = [NSString stringWithFormat:@"%@:%@:%@:%@", timeString, pRoomString, parkingString, smokingString];
    // write othersString to othersString.txt file
    fileName= [NSHomeDirectory() stringByAppendingPathComponent:@"tmp/othersString.txt"];
    NSData *othersData = [othersString dataUsingEncoding:NSUTF8StringEncoding];
    [fileManager createFileAtPath:fileName contents:othersData attributes:nil];
    // make row data in string
    NSString *rowString = [NSString stringWithFormat:@"%i:%i:%i:%i", row0,row1,row2,row3];
    // write othersString to othersString.txt file
    fileName = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp/rowString.txt"];
    NSData *rowData = [rowString dataUsingEncoding:NSUTF8StringEncoding];
    [fileManager createFileAtPath:fileName contents:rowData attributes:nil];
    // pop the controller
    [self.navigationController popViewControllerAnimated:YES];
}
- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}
- (void)dealloc {
    [super dealloc];
    [list release];
}
@end

Got this stuff from this post, as this was in Japanese I changed it. Thanks to the author.

Upvotes: 0

Midhun MP
Midhun MP

Reputation: 107121

This won't be a good solution. Use a NSMutableArray for storing the selected sections.

NSMutableArray *selectedSections; //instance variable

selectedSections= [[NSMutableArray alloc] init];   //in viewDidLoad

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
   NSNumber *section = [NSNumber numberWithInt:indexPath.section];
   if([selectedSections containsObject:section]
      return nil;
   else
   {
      [selectedSections addObject:section];
      return indexPath;
   }
}

When you deselect a row write the below code there:

[selectedSections removeObject:[NSNumber numberWithInt:indexPath.section]];

Upvotes: 2

Venk
Venk

Reputation: 5955

try like this,

In .h

@property (nonatomic, retain) NSIndexPath *checkedIndexPath;

In .m

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ 


    if(indexPath.section==0)
    {

        // to check and Uncheck the row
        if(self.checkedIndexPath)
        {
            UITableViewCell* uncheckCell = [tableView1
                                            cellForRowAtIndexPath:self.checkedIndexPath];
            uncheckCell.accessoryType = UITableViewCellAccessoryNone;
        }
        if([self.checkedIndexPath isEqual:indexPath])
        {
            self.checkedIndexPath = nil;
        }
        else
        {
            UITableViewCell* cell = [tableView1 cellForRowAtIndexPath:indexPath];
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
            self.checkedIndexPath = indexPath;
        }

    }
}

Upvotes: 1

Manish Agrawal
Manish Agrawal

Reputation: 11026

  1. Keep a property in your view controller called selectedRow, which represents the indexPath of tableview that represents the checked item in a table section.

  2. In your view controller's -tableView:cellForRowAtIndexPath: delegate method, set the accessoryType of the cell to UITableViewCellAccessoryCheckmark if the cell's indexPath equals the selectedRow indexpath value. Otherwise, set it to UITableViewCellAccessoryNone.

  3. In your view controller's -tableView:didSelectRowAtIndexPath: delegate method, set the selectedRow value to the indexPath.row that is selected, e.g.: self.selectedRow = indexPath.row

Upvotes: 2

Related Questions