0

I know this question is very similar to other questions, but i doesn't resolve the problem using that approach.i follow most of the available solution but it doesn't work for me.. I know that when tableview scrolls it reuse cell but i doesn't know the approach of maintaining the button state . i'll try with following link

I done all the things.use tags, use touch points and all but nothing seems to work for me.so help me out..and here is my sample code

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];


/*
 *  Set button for cell to subscribe with it
 */
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;


[cell.btnsubscribe addTarget:self action:@selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];

if (![_arraybtnState containsObject:listid] )
    {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
        [cell.btnsubscribe setSelected:YES];
    }
    else {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
        [cell.btnsubscribe setSelected:NO];
    }

  return cell;
  }

_arrbtnstate contains the ids that user follows.
and listid contains unique id comes from database too

And the click event method...

- (IBAction)clickBtnSubscribe:(id)sender {

UIButton *button = (UIButton*)sender;
NSLog(@"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];

if (button.selected) {
    [self.arraybtnState addObject:tagnum];
    [button setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    NSLog(@"Subscribe");
    [self subscribeButton:button.tag];
    [button setSelected:NO];
}
else
{
    [self.arraybtnState removeObject:tagnum];
    [button setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    NSLog(@"unsubscribe");
    [self unsubscribeButton:button.tag];
    [button setSelected:YES];
}

}   

Note: In this code, button is created in storyboard.,but i'll also tried without storyboard too.

Community
  • 1
  • 1
Bhavin Bhadani
  • 22,224
  • 10
  • 78
  • 108
  • This could not work because you always use the same button for all cells. You have to create a new button for the cell. – Thallius Apr 08 '15 at 07:03
  • Refer my answer for swift 2.1. Works well. http://stackoverflow.com/questions/25257378/how-to-use-reusable-cells-in-uitableview-for-ios – Deepak Thakur Mar 02 '16 at 12:34

5 Answers5

1

First of all this line cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303]; is to be changed. Follow the below steps and try

  1. in custom subcategoryCell connect IBOutlet to btnsubscribe.
  2. in storyboard, you can set both selected and not normal images to a UIButton, here it is btnsubscribe. If you find it difficult follow this
  3. in cellForRowAtIndexPath: remove below lines

    [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
    
  4. update the following lines

    if (![_arraybtnState containsObject:listid] )
    {
         [cell.btnsubscribe setSelected:YES];
    }
    else {
         [cell.btnsubscribe setSelected:NO];
    }
    

or simply [cell.btnsubscribe setSelected:(![_arraybtnState containsObject:listid] )];

  1. Keep the addTarget in cell for row method (since you have custom cell class, it is better to move the button action to cell class and pass the result to viewcontroller by callback or delegate. not discussing that now but recomments) and update the clickBtnSubscribe: by removing

    [button setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    [button setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    

these lines. assumes other parts are working properly.

Community
  • 1
  • 1
Akhilrajtr
  • 5,170
  • 3
  • 19
  • 30
  • ok i'll try with this...but now i am using swift and not use custom class...so for this i have to make new custom class with xib? right – Bhavin Bhadani May 21 '15 at 07:31
  • if you are using storyboard you can add custom prototype cells in storyboard itself. the idea is to set two different images for 2 states of uibutton and change its state only. the image will automatically changes – Akhilrajtr May 21 '15 at 07:35
  • and with using custom cell, you can connect IBOutlet and no need to get the button with view with tag option. also can update the tag with indexpath to indentify the row – Akhilrajtr May 21 '15 at 07:37
  • ohhh...man ...where are from this much days....whooo....great going and working well for me...thanx dude – Bhavin Bhadani May 21 '15 at 07:51
  • welcome @Bhavin .. happy to know that it worked for you.. if you have enough time, try moving action of uibutton in cell to custom cell class and send desired response to viewcontroller by callback :). happy coding.. – Akhilrajtr May 21 '15 at 08:08
  • check [this](http://stackoverflow.com/questions/27439727/detecting-taps-on-custom-cells-of-uitableview/27439847#27439847), let me know if you have any doubt – Akhilrajtr May 21 '15 at 08:25
0

You are setting Selected and unselected image for button's Normal state in both cases i.e UIControlStateNormal. When you are using selected method you do not require to setImage again. Just set Image for Normal and selected state for button properly in cellForRowAtIndexpath or in xib. You are done.

First remove the setting image in clickBtnSubscribe:() method.

Now in your storyboard set images for Normal and selected state. Also remove set Image in cell for row at indexpath as you have already done in view.

Samir
  • 902
  • 9
  • 23
0

You can maintain the state of the buttons as-

// initialize your array only once

_arraybtnState = [[NSMutableArray alloc] init];

// cell for row at index path would be

//initially each cell will have follow image

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];

[cell.btnsubscribe setTag: indexPath.row];
[cell.btnsubscribe addTarget:self action:@selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];

    if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] )
    {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
        [cell.btnsubscribe setSelected:YES];
    }
    else 
    {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
        [cell.btnsubscribe setSelected:NO];
    }

  return cell;
  }

- (IBAction)clickBtnSubscribe:(id)sender {

UIButton *button = (UIButton*)sender;
NSLog(@"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];

if (button.selected) {
    [self.arraybtnState addObject:tagnum];
    NSLog(@"Subscribe");
    [self subscribeButton:button.tag];
    [button setSelected:NO];
}
else
{
    [self.arraybtnState removeObject:tagnum];
    NSLog(@"unsubscribe");
    [self unsubscribeButton:button.tag];
    [button setSelected:YES];
}

    //after doing modification update the respective row as

    UIButton *button = (UIButton *)sender;

    // Find Point in Superview
    CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];

    // Infer Index Path
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInSuperview];

    //relaod the row
    NSArray* indexPathModel = [NSArray arrayWithObjects:indexPath, nil];
    [self.tableView reloadRowsAtIndexPaths: indexPathModel withRowAnimation:UITableViewRowAnimationNone];

}

reloading row will reflect the changes done in the modal to the UI.

Sanjay Mohnani
  • 5,947
  • 30
  • 46
0

I think you can put this line in viewDidLoad or after you load what all have subscribed .

   _arraybtnState = [NSMutableArray arrayWithArray:[self.strSubscribe componentsSeparatedByString:@","]];

Then the cellForRowAtIndexPath will loook like below

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  cell = (subcategoryCell *)[tableView dequeueReusableCellWithIdentifier:NSStringFromClass([subcategoryCell class]) forIndexPath:indexPath];


/*
 *  Set button for cell to subscribe with it
 */
cell.btnsubscribe = (UIButton *)[cell.contentView viewWithTag:303];
cell.btnsubscribe.tag = indexPath.row ;

[cell.btnsubscribe addTarget:self action:@selector(clickBtnSubscribe:) forControlEvents:UIControlEventTouchUpInside];

     if (![_arraybtnState containsObject:[NSNumber numberWithInt:indexPath.row]] ) {

        [cell.btnsubscribe setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    }
    else {
        [cell.btnsubscribe setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    }

  return cell;
  }

and then the btn click method as

- (IBAction)clickBtnSubscribe:(id)sender {

UIButton *button = (UIButton*)sender;
NSLog(@"selected button tag %li", (long)button.tag);
NSNumber *tagnum = [NSNumber numberWithLong:(long)button.tag];


  if (![_arraybtnState containsObject:tagnum] )
  {
      [_arraybtnState addObject:tagnum];
      [button setImage:[UIImage imageNamed:@"following"] forState:UIControlStateNormal];
    NSLog(@"Subscribe");
    [self subscribeButton:button.tag];


    }
    else {

    [self.arraybtnState removeObject:tagnum];
    [button setImage:[UIImage imageNamed:@"follow"] forState:UIControlStateNormal];
    NSLog(@"unsubscribe");
    [self unsubscribeButton:button.tag];


    }

}  
Bharat Jagtap
  • 1,692
  • 2
  • 22
  • 35
0

Two easy solutions and quite fast to implement :

  1. Keep track of the state in an array/dictionary

You can store your states in an array of states, i'll make an example.

(Note: i'm coding this without compiling, I might mispel some stuff, feel free to edit my post)

in your viewDidLoad

  arrState = [[NSMutableArray alloc]init];
  for (yourObject *object in dataArray){  
      //For every object that you use to load your tableview, this can be strings or anything really
       [arrState addObject:@NO];

    }

In your cellForRow

...
//This will either put YES or NO depending on the element in the state array.
[cell.button setSelected:[arrState objectAtIndex:indexPath.row]];
...

Boom, done.

  1. You can also keep track of this in a database or anything persistent, and then you'd simply load whatever your field contains for a selected record. This is more relevant if we're talking about, for example, something like favourites or something that will be there until the user decides otherwise. If it's just to keep track of your button states during the lifetime of your view, then ignore this part of the answer.

If you need to keep it alive forever (even when the app closes), then you'd most probably need a database :)

Gil Sand
  • 5,802
  • 5
  • 36
  • 78