Search code examples
iosobjective-cuitableviewuislider

UISlider Value Automatically assigned while scrolling in UITable View Cell


I am Working on a Program which looks like this:

There is a Table View i that there is a Custom Table View Cell. And there is a UISlider , Label and Button on Custom View Cell

enter image description here

enter image description here

Now the Problem is when i slide the UISlider of Cell : 0 than the UISlider at Cell : 12(or later Cell) is Automatically assigned the Cell:0's UISlider Value(Thanks To ARC..!!).

Now anyone have a solution so that the later cell's UISlider doest change while i change value of upper Cells.

P.S. When i assigned a UiSlider Value at Cell:0 and Scroll Up and Down it is automatically random Cell's UISlider Value is changing.

Google Drive Link of Project : Slider Program

I am Using xCode 5 and iOS SDK 7.

Thanks for Reading.

Edit: cellForRowAtIndexPath Method

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    static NSString *simpleTableCell = @"Cell";

    CustomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableCell];


    if (cell == nil) {
        cell = [[CustomeTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableCell];
    }

    NSString *strName = [NSString stringWithFormat:@"Cell : %d",indexPath.row];
//    NSLog(@"strName :%@ , SliderValue : %d",strName , (int)cell.mySlider.value);


    for (int i = 0; i < arrSlider.count; i++) {

        NSString *strTag = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]valueForKey:@"tag"]];
        NSString *myIndexPath = [NSString stringWithFormat:@"%d",indexPath.row];

        if([strTag isEqualToString:myIndexPath])
        {
            NSString *strValue = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]valueForKey:@"value"]];

            cell.mySlider.value = [strValue floatValue];
            NSLog(@"Tag Value : %@ , value %f", strTag , [strValue floatValue]);

        }

    }

    [cell.btnCell setTitle:strName forState:UIControlStateNormal];

    cell.btnCell.tag = indexPath.row;
    cell.mySlider.tag = indexPath.row;

    [cell.mySlider addTarget:self action:@selector(customSliderValue:) forControlEvents:UIControlEventValueChanged];

    [cell.btnCell addTarget:self action:@selector(customeBtnClicked:) forControlEvents:UIControlEventTouchDown];

    return cell;

}

Solution

  • Use NSMutableDictionary to hold the values of slider then update it from the cellForRowAtIndexPath method i am posting the changes just make changes in your project

    in ViewCOntroller.h file

    #import <UIKit/UIKit.h>
    #import "CustomeTableViewCell.h"
    
    @interface ViewController : UIViewController <UITableViewDataSource ,UITableViewDelegate,SliderDelegate>//confirms to delegate
    {
      //NSArray *tableList;
      UITableView *mytableview;
      NSInteger SliderChangeValue;
    
    }
    
    @property (strong , nonatomic) IBOutlet UIView *tableDemo;
    @property (strong , nonatomic) NSMutableArray *arrSlider;
    @property (strong,  nonatomic) NSMutableDictionary *sliderDicValues; //add a mutable dictionary 
    @property (weak, nonatomic) IBOutlet UITableView *myTableView;//add outlet to tableview
    
    @end
    

    in ViewController.mfile

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    @synthesize arrSlider;
    @synthesize sliderDicValues;
    
    - (void)viewDidLoad  
    {
      [super viewDidLoad];
      // Do any additional setup after loading the view, typically from a nib.
      //    tableList = [NSArray arrayWithObjects:
      //                 @"Cell 1",@"Cell 2",@"Cell 3",@"Cell 4",@"Cell 5",
      //                 @"Cell 6",@"Cell 7",@"Cell 8",@"Cell 9",@"Cell 10",
      //                 @"Cell 11",@"Cell 12",@"Cell 13",@"Cell 14",@"Cell 15",
      //                 @"Cell 16",@"Cell 17",@"Cell 18",@"Cell 19",@"Cell 20",
      //                 nil];
    
       arrSlider = [[NSMutableArray alloc]init];
       sliderDicValues = [[NSMutableDictionary alloc]init]; //initilise an mutable dictionary
      //[mytableview registerClass:[CustomeTableViewCell class]       forCellReuseIdentifier:@"Cell"];
    }
    
    - (void)didReceiveMemoryWarning
    {
       [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
     //[tableList count] 
      return 15;
     }
    
     -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
       static NSString *simpleTableCell = @"Cell";
       CustomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableCell];
       if (cell == nil) {
          cell = [[CustomeTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableCell];
       }
       if([self.sliderDicValues objectForKey:[NSString stringWithFormat:@"%d",indexPath.row]]) //check if there is any slided value is present
       {
         NSNumber *value = [self.sliderDicValues objectForKey:[NSString stringWithFormat:@"%d",indexPath.row]];
         [cell.mySlider setValue:value.integerValue]; //set the slider value
         [cell.myCellLabel setText:[NSString stringWithFormat:@"%d",value.integerValue]];//and also label
       }
       else //set to default values
       {
          [cell.mySlider setValue:(NSInteger)0];
          [cell.myCellLabel setText:@"label"];
       }
       //add a single target don't add double target to slider 
       cell.sliderDelegate = self;//set the delegate
       return cell;
    /*
     NSString *strName = [NSString stringWithFormat:@"Cell : %d",indexPath.row];
     NSLog(@"strName :%@ , SliderValue : %d",strName , (int)cell.mySlider.value);
     for (int i = 0; i < arrSlider.count; i++) {
         NSString *strTag = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]valueForKey:@"tag"]];
         NSString *myIndexPath = [NSString stringWithFormat:@"%d",indexPath.row];
    
         if([strTag isEqualToString:myIndexPath])
         {
             NSString *strValue = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]valueForKey:@"value"]];
    
             cell.mySlider.value = [strValue floatValue];
             NSLog(@"Tag Value : %@ , value %f", strTag , [strValue floatValue]);    
         }
    
         if ([strTag isEqual:myIndexPath]) {
             //NSString *strValue = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]objectForKey:@"value"]];
             //NSLog(@"%@",strValue);
             NSLog(@"Hello");
             //cell.mySlider.value =
         }
     }
     [cell.btnCell setTitle:strName forState:UIControlStateNormal];
     cell.btnCell.tag = indexPath.row;
     cell.mySlider.tag = indexPath.row;
     [cell.mySlider addTarget:self action:@selector(customSliderValue:) forControlEvents:UIControlEventValueChanged];
     [cell.btnCell addTarget:self action:@selector(customeBtnClicked:) forControlEvents:UIControlEventTouchDown];
     */
    }
    
    //delegate method called from custom cell 
    - (void)sliderChanged:(CustomeTableViewCell *)cell
    {
       NSIndexPath *path = [_myTableView indexPathForCell:cell]; //get the indexpath
       if(path)//check if valid path
       {
          SliderChangeValue = cell.mySlider.value;
          [self.sliderDicValues setObject:[NSNumber numberWithInt:SliderChangeValue] forKey:[NSString stringWithFormat:@"%d",path.row]]; //set the value in the dictionary later used in the cellForRowAtIndexPath method
       }
       //     SliderChangeValue = (int)sender.value;
            NSLog(@"%d",SliderChangeValue);
    }
    
    
     //dont use it
     -(void)customSliderValue:(UISlider *)sender{
    
     //    NSString *value =[NSString stringWithFormat:@"%d" ,(int)sender.value];
     //    NSString *tag = [NSString stringWithFormat:@"%d", (int)sender.tag];
     //    
     //    NSLog(@"%@ %@",value , tag);
     //    
     //    [self.dicSilder setObject:value forKey:@"value"];
     //    [self.dicSilder setObject:tag forKey:@"tag"];
     //    
     //    [self.arrSlider addObject:self.dicSilder]; 
     //    NSLog(@"%@",self.arrSlider);
    
    
        SliderChangeValue = (int)sender.value;
    
        NSLog(@"%d",SliderChangeValue);
    
     }
    
     //this is also put a delegate from the cell like slider , just add the another method in the protocol and perform action, if u don't get just comment i will update the code and u hav t modify this method according to your requirement
     -(void)customeBtnClicked:(UIButton *)sender
     { 
        NSString *value =[NSString stringWithFormat:@"%d" ,SliderChangeValue];
        NSString *tag = [NSString stringWithFormat:@"%d", sender.tag];
    
        //NSLog(@"%@ %@",value,tag);
        NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
        [dic setObject:value forKey:@"value"];
        [dic setObject:tag forKey:@"tag"];
    
        //NSLog(@"%@",dic);
    
        [arrSlider addObject:dic];
    
    
         NSLog(@"%@",arrSlider);
    
         NSString *sliderTagAtIndexPath = @"";
        //NSString *sliderValueAtindexPath = @"";
    
         for (int i = 0; i < arrSlider.count; i++) {
    
         NSString *strTag = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]valueForKey:@"tag"]];
    
          if([strTag isEqualToString:tag])
          {       
            //NSString *strValue = [NSString stringWithFormat:@"%@",[[arrSlider objectAtIndex:i]valueForKey:@"value"]];
    
            sliderTagAtIndexPath = strTag;
            //sliderValueAtindexPath = strValue; 
         }
        }
        UIAlertView *myAlertView = [[UIAlertView alloc]initWithTitle:@"Clicked"
                                                         message:[NSString stringWithFormat:@"Cell : %@ Value: %d", sliderTagAtIndexPath ,SliderChangeValue]
                                //message:[NSString stringWithFormat:@"Cell : %@ Value: %@", sliderTagAtIndexPath ,sliderValueAtindexPath]
                                                        delegate:self
                                               cancelButtonTitle:@"OK"
                                               otherButtonTitles:nil];
    
        [myAlertView show];
    
    }
    @end
    

    in CustomeTableViewCell.h file

    #import <UIKit/UIKit.h>
    //add a custom delegate
    @protocol SliderDelegate<NSObject>
    - (void)sliderChanged:(id)self;
    @end
    
    @interface CustomeTableViewCell : UITableViewCell
    
    @property (weak, nonatomic) IBOutlet UILabel *myCellLabel;
    @property (weak, nonatomic) IBOutlet UISlider *mySlider;
    @property (weak, nonatomic) IBOutlet UIButton *btnCell;
    @property (weak, nonatomic) id <SliderDelegate>sliderDelegate;
    
     - (IBAction)sliderValuechanged:(UISlider *)sender;
    
    @end
    

    in CustomeTableViewCell.m file

     #import "CustomeTableViewCell.h"
    
     @implementation CustomeTableViewCell
    
     - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
     {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
         // Initialization code
        }
        return self;
    }
    
    - (void)awakeFromNib
    {
       // Initialization code
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated
    {
        [super setSelected:selected animated:animated];
    
        // Configure the view for the selected state
    }
    
    - (IBAction)sliderValuechanged:(UISlider *)sender
    {
       self.myCellLabel.text = [NSString stringWithFormat:@"%d",(NSInteger)sender.value];
       //call the custom delegate each time when slider is slided
       if([_sliderDelegate respondsToSelector:@selector(sliderChanged:)])
       {
           [_sliderDelegate sliderChanged:self]; //passing the entire cell itself
       } 
    }
    @end
    

    Hope this helps u .. :)