srinitha
srinitha

Reputation: 119

Expandable UITableview cell using NSDictionary in iOS

Here is my code:

Viewcontroller.m

@interface ViewController ()
{
    NSArray *sectionTitleArray;
    NSMutableArray *arrayForBool;

    NSArray *aboutStep0neArray;
    NSArray *profileArray;
}

@property (nonatomic, strong) IBOutlet UITableView *tablevw;

- (void)viewDidLoad
{
    [super viewDidLoad];

    _tablevw.delegate = self;
    _tablevw.dataSource = self;

    arrayForBool = [[NSMutableArray alloc]init];

    sectionTitleArray = @[ @{@"text": @"About Step0ne"},
                           @{@"text": @"Profile"},
                           @{@"text": @"Matches"},
                           @{@"text": @"Messages"},
                           @{@"text": @"Photos"},
                           @{@"text": @"Settings"},
                           @{@"text": @"Privacy"},
                           @{@"text": @"Reporting issues"},
                          ];

    aboutStep0neArray = @[ @{@"text1": @"stepone1"},
                           @{@"text1": @"stepone2"},
                           @{@"text1": @"stepone3"},
                           @{@"text1": @"stepone4"},
                           @{@"text1": @"stepone5"},
                           @{@"text1": @"stepone6"},
                           @{@"text1": @"stepone7"},
                           @{@"text1": @"stepone8"},
                         ];

    profileArray = @[ @{@"text2": @"profile1"},
                      @{@"text2": @"profile2"},
                      @{@"text2": @"profile3"},
                      @{@"text2": @"profile4"},
                      @{@"text2": @"profile5"},
                      @{@"text2": @"profile6"},
                      @{@"text2": @"profile7"},
                      @{@"text2": @"profile8"},
                    ];



    for (int i=0; i<[sectionTitleArray count]; i++)
    {
        [arrayForBool addObject:[NSNumber numberWithBool:NO]];

    }

}

#pragma mark:- UITableView Delegate and Datasource Methods

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return sectionTitleArray.count;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if ([[arrayForBool objectAtIndex:section] boolValue])
    {
        if (section == 0)
        {
            return [aboutStep0neArray count];
        }
        else if (section == 1)
        {
            return [profileArray count];
        }
     }
     return 1;
 }  

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
  reuseIdentifier:cellIdentifier];
    }
    BOOL manyCells = [[arrayForBool objectAtIndex:indexPath.section]boolValue];

    if (!manyCells)
    {
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.text = @"";
    }
    else
    {
        if (indexPath.section == 0)
        {
            cell.textLabel.text = [[aboutStep0neArray objectAtIndex:indexPath.row]objectForKey:@"text1"];
        }
        else if (indexPath.section == 1)
        {
            cell.textLabel.text = [[profileArray objectAtIndex:indexPath.row]objectForKey:@"text2"];
        } 
    }
    return cell;
}


 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
/*************** Close the section, once the data is selected ***********************************/
    [arrayForBool replaceObjectAtIndex:indexPath.section withObject:[NSNumber
  numberWithBool:NO]];

    [_tablevw reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]
  withRowAnimation:UITableViewRowAnimationAutomatic];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([[arrayForBool objectAtIndex:indexPath.section] boolValue])
    {
        return 40;
    }
    return 0;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40;
}

#pragma mark - Creating View for TableView Section

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *sectionView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 280,40)];
    sectionView.tag=section;
    UILabel *viewLabel=[[UILabel alloc]initWithFrame:CGRectMake(13, 0, _tablevw.frame.size.width-10,
  40)];
    viewLabel.backgroundColor=[UIColor clearColor];
    viewLabel.textColor=[UIColor purpleColor];
    viewLabel.font=[UIFont systemFontOfSize:15];
    viewLabel.text=[sectionTitleArray objectAtIndex:section];
    [sectionView addSubview:viewLabel];

    /********** Add a custom Separator with Section view *******************/
    UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(12, 40, _tablevw.frame.size.width-35, 1)];
    separatorLineView.backgroundColor = [UIColor purpleColor];
    [sectionView addSubview:separatorLineView];

    /********** Add UITapGestureRecognizer to SectionView   **************/

    UITapGestureRecognizer  *headerTapped   = [[UITapGestureRecognizer alloc] initWithTarget:self
  action:@selector(sectionHeaderTapped:)];

    [sectionView addGestureRecognizer:headerTapped];

    return  sectionView; 
 }

#pragma mark - Table header gesture tapped

- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gestureRecognizer
{
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:gestureRecognizer.view.tag];

    if (indexPath.row == 0)
    {
        BOOL collapsed  = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
        for (int i=0; i<[sectionTitleArray count]; i++)
        {
            if (indexPath.section==i)
            {
                [arrayForBool replaceObjectAtIndex:i withObject:[NSNumber numberWithBool:!collapsed]];
            }
        }
        [_tablevw reloadSections:[NSIndexSet indexSetWithIndex:gestureRecognizer.view.tag]
  withRowAnimation:UITableViewRowAnimationAutomatic];

     }

     [_tablevw reloadData];
}

First in tableview sectionTitleArray objects should display.After that when I click the About Stepone row it should expand with aboutSteponeArray objects and after clicking again it should collapse.Same incase of profileArray too. AboutSteponeArray and profileArray are the sections of the sectionTitleArray.

When I run my code I'm getting:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI rangeOfCharacterFromSet:]: unrecognized selector sent to instance 0x7f9cfb4bf880' error.

Upvotes: 3

Views: 454

Answers (2)

Niko
Niko

Reputation: 3422

Your arrays are incorrectly instanciated : don't add a comma , after the last element in each array

sectionTitleArray = @[ @{@"text": @"About Step0ne"},
                       @{@"text": @"Profile"},
                       @{@"text": @"Matches"},
                       @{@"text": @"Messages"},
                       @{@"text": @"Photos"},
                       @{@"text": @"Settings"},
                       @{@"text": @"Privacy"},
                       @{@"text": @"Reporting issues"}
                     ];

aboutStep0neArray = @[ @{@"text1": @"stepone1"},
                       @{@"text1": @"stepone2"},
                       @{@"text1": @"stepone3"},
                       @{@"text1": @"stepone4"},
                       @{@"text1": @"stepone5"},
                       @{@"text1": @"stepone6"},
                       @{@"text1": @"stepone7"},
                       @{@"text1": @"stepone8"}
                     ];

profileArray = @[ @{@"text2": @"profile1"},
                  @{@"text2": @"profile2"},
                  @{@"text2": @"profile3"},
                  @{@"text2": @"profile4"},
                  @{@"text2": @"profile5"},
                  @{@"text2": @"profile6"},
                  @{@"text2": @"profile7"},
                  @{@"text2": @"profile8"}
                ];

EDIT :

The source of your problem is in - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section at the following line :

viewLabel.text=[sectionTitleArray objectAtIndex:section];

Since each element of your sectionTitleArray is a NSDictionnary, you are then assigning a NSDictionnay to a the label tetxt attribute which is NSString typed.

Since all the keys in all dictionnaries stored in sectionTitleArray are @"text" , replace with the following :

viewLabel.text= [[sectionTitleArray objectAtIndex:section] objectForKey:@"text"];

Upvotes: 2

I checked your code & found few issues. Here is the corrected code:

First Removed Key Values from Array:

sectionTitleArray = [NSArray arrayWithObjects:@"About Step0ne", @"Profile", @"Matches", @"Messages", @"Photos", @"Settings", @"Privacy", @"Reporting issues", nil];
aboutStep0neArray = [NSArray arrayWithObjects:@"stepone1", @"stepone2", @"stepone3", @"stepone4", @"stepone5", @"stepone6", @"stepone7", @"stepone8", nil];
profileArray = [NSArray arrayWithObjects:@"profile1", @"profile2", @"profile3", @"profile4", @"profile5", @"profile6", @"profile7", @"profile8", nil];

Reason: You have given common keys to all objects than why its needed to give keys. That was creating an issue so removed.

Than: In Tableview method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    BOOL manyCells = [[arrayForBool objectAtIndex:indexPath.section] boolValue];
    if (!manyCells) {
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.text = @"";
    } else {
        if (indexPath.section == 0) {
            cell.textLabel.text = [aboutStep0neArray objectAtIndex:indexPath.row];
        } else if (indexPath.section == 1) {
            cell.textLabel.text = [profileArray objectAtIndex:indexPath.row];
        }
    }
    return cell;
}

This is the only change i have done & tested. It worked fine for me.

Hope it will work for you.

Upvotes: 0

Related Questions