Search code examples
iosiphoneobjective-ccell

transfer variable with button in custom cell iphone


Hye everybody!! i have a problem that i don't know what can i do!! My goal is transfer a variable of one TableviewController in other ViewController when i clic in the buttom in customcell. I use a Custom Cell and in the customcell i have 2 label, one buttom. this is my code:

ArticlesCell.h

#import <UIKit/UIKit.h>
#import "CalculerViewController.h"
@interface ArticlesCell : UITableViewCell
@property (strong, nonatomic) IBOutlet UILabel *lblproduit;
@property (strong, nonatomic) IBOutlet UILabel *lblargent;
- (IBAction)btnincrement:(id)sender;
@property (strong, nonatomic) IBOutlet UIButton *btn;
@property (strong, nonatomic) NSString  *recupererlblproduit;
@end

the one tableviewcontroller:

ArticlesTableViewController.m

#import "ArticlesTableViewController.h"
#import "ArticlesCell.h"


@interface ArticlesTableViewController ()

@end

@implementation ArticlesTableViewController
@synthesize arrayargent1,arrayproduit1,arrayargent2,arrayproduit2,recuperationproduit;
- (id)initWithStyle:(UITableViewStyle)style
{
  self = [super initWithStyle:style];
  if (self) {
    // Custom initialization
  }
  return self;
}

- (void)viewDidLoad
{
  [super viewDidLoad];

  recuperationproduit=nil;
  arrayproduit1 = [[NSMutableArray alloc] initWithObjects:@"Câble Ethernet UTP-CAT5 ",@"Câble Ethernet UTP-CAT6 ",@"Carte Réseau",@"Hub",@"Switch",@"Routeur",nil];
  arrayargent1 = [[NSMutableArray alloc] initWithObjects:@"10 000",@"15 000 ",@"250 000",@"300 000",@"500 000",@"550 000",nil];
  arrayproduit2 = [[NSMutableArray alloc] initWithObjects:@"Ram ",@"Disque Dur",@"Câble d'Alimentation",@"Carte Mere",@"Processeur",nil];
  arrayargent2 = [[NSMutableArray alloc] initWithObjects:@"100",@"15 000 ",@"250 000",@"300 000",@"500 000",@"550 000",nil];



}

- (void)didReceiveMemoryWarning
{
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

  return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

 if (section == 0)
    return self.arrayproduit1.count;
 if (section == 1)
    return self.arrayproduit2.count;
 return 0;
}


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
  if (section == 0)
    return @"Matériels Réseaux";
  if (section == 1)
    return @"Matériels Ordinateur";
  return @"undefined";
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if ([segue.identifier isEqualToString:@"seguecalcule"])
  {
    UINavigationController *navigationController = segue.destinationViewController;
    CalculerViewController *calculerViewController = [[navigationController viewControllers] objectAtIndex:0];
            calculerViewController.introlblproduit=recuperationproduit;
            calculerViewController.delegate = self;

  }


}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *CellIdentifier = @"CellArticle";



ArticlesCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[ArticlesCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}


if (indexPath.section == 0){
    cell.lblproduit.text = [arrayproduit1 objectAtIndex:indexPath.row];
    cell.lblargent.text = [self.arrayargent1 objectAtIndex:indexPath.row];

}
else if (indexPath.section == 1){
    cell.lblproduit.text = [self.arrayproduit2 objectAtIndex:indexPath.row];
    cell.lblargent.text = [self.arrayargent2 objectAtIndex:indexPath.row];

}  

return cell;
}

- (void)calculerViewControllerDidCancel:(CalculerViewController *)cancel
{
 [self dismissViewControllerAnimated:YES completion:nil];
}



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


}

@end

CalculerViewController.m

#import "CalculerViewController.h"
@interface CalculerViewController ()

@end

@implementation CalculerViewController
@synthesize display,lbltitre,delegate,introlblproduit;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  if (self) {
    // Custom initialization
  }
  return self;
}

- (void)viewDidLoad
{
  [super viewDidLoad];
  lbltitre.text=introlblproduit;


}

- (void)didReceiveMemoryWarning
{
 [super didReceiveMemoryWarning];
 // Dispose of any resources that can be recreated.
}

- (IBAction)valider:(id)sender {
}

- (IBAction)cancel:(id)sender {

[self.delegate calculerViewControllerDidCancel:self];
}
@end

I want to transfer the label of my custom cell when i clic in the buttom. Help me please!!


Solution

  • The simplest answer is to directly connect the button in each cell to the same method in your view controller and then use the sender parameter to access the tapped cell.

    Something like this (not tested):

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"CellArticle";
    
        ArticlesCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
           cell = [[ArticlesCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
    
        // When the user taps the cell button, fire a method on the view controller
        [cell.btn addTarget:self action:@selector(cellButtonTapped:) forControlEvents:UIControlEventsTouchUpInside];
    
        ...
    }
    
    - (void) cellTapped:(id)sender
    {
        ArticleCell *cell = sender.parent; // XXX: This is where it gets ugly!
        // Now send your cell content to your other view controller.
    }
    

    But as you can see that approach gets really ugly in that you have to know about the view hierarchy within the cell.

    So, a much better approach is to use the delegate pattern: have the UITableViewCell subclass have a delegate that you connect to your UIViewController instance.

    In your case, it would look something like this:

    // Forward declaration required because protocol references class
    @protocol ArticlesCellDelegate;
    
    @interface ArticlesCell : UITableViewCell
    @property (strong, nonatomic) IBOutlet UILabel *lblproduit;
    @property (strong, nonatomic) IBOutlet UILabel *lblargent;
    - (IBAction)btnincrement:(id)sender;
    @property (strong, nonatomic) IBOutlet UIButton *btn;
    @property (strong, nonatomic) NSString  *recupererlblproduit;
    
    // New delegate property
    @property (strong, nonatomic) id<ArticleCellDelegate> delegate;
    
    @end
    
    @protocol ArticlesCellDelegate
      - (void) didTapButtonInArticleCell:(ArticleCell*)cell;
    @end
    

    Then in your view controller:

    @interface ArticlesTableViewController () <ArticleCellDelegate>
    
    @end
    
    @implementation ArticlesTableViewController
    
    ...
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *CellIdentifier = @"CellArticle";
    
        ArticlesCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
           cell = [[ArticlesCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }
    
        // Make the view controller the cell's delegate
        cell.delegate = self;
        ...
    }
    
    - (void) didTapButtonInArticleCell:(ArticleCell*)cell  {
    
        // Now send your cell content to your other view controller.
    }
    

    The other thing you need is in your article cell class, you need to handle the delegate when the button is tapped. Your btnIncrement: method can do that:

    @implementation ArticleCell
    
    ...
    - (IBAction)btnincrement:(id)sender;
    {
        if( self.delegate )
            [self.delegate didTapButtonInArticleCell:self];
    }
    

    As a side note, if I were you I'd move as many of those UI elements out of the interface definition as I could. The interface section is exactly what it says: a place to define the interface. You usually want to encapsulate the inner workings of your view in the implementation section and have the interface section just reflect the way you want it to be used.