Souchan Meijin
Souchan Meijin

Reputation: 43

Call and use uitableview from uitableviewcell?

I have a UITableViewController with many UITableViewCell. Each Cell have a UISwitch Button.

Here is my UITableViewController Class:

@implementation DanhsachTableViewController{
    NSMutableArray *data;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadData];
}

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        DichVu2TableViewCell *cell = (DichVu2TableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"dscell"];
        NSDictionary *dataCell =  data[indexPath.row];
        cell.service =  dataCell[@"service"];
        cell.package =  dataCell[@"package"];
        cell.loai_goi = dataCell[@"loai_goi"];

        return cell;
    }
-(void) changeCellState:(NSString *)service package:(NSString *)package loaigoi:(NSString *)loai_goi{
    for (int i =0;i<data.count;i++){
        DichVu2TableViewCell *cellLocal = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
        if ([service isEqualToString:cellLocal.service] && ![package isEqualToString:cellLocal.package] && [loai_goi isEqualToString:cellLocal.loai_goi]){
            [cellLocal.sudung setOn:NO animated:YES];
        }
     }
}

"Data" array was loaded in method loadData (not important here so I don't include it).

In UITableViewCell (class name: DichVu2TableViewCell), I set event Value Change of Switch so that each time a Switch change value (ON for example), all other cell's switch which have the same value "service" and "loai_goi" will be set OFF.

DanhsachTableViewController *tableview = [[DanhsachTableViewController alloc] init];
    tableview.tableView.delegate = (DanhsachTableViewController *)self.superview.superview;
[tableview changeCellState:_service package:_package loaigoi:_loai_goi];

But when I call, the array "data" of above tableview have 0 object so nothing happened.

Is there any way to do that?

Hi Oyeoj, Thanks for your help.

I have a little problem when followed your guide. There are some error in xcode when I use extract your code so I have to customize. But the program still has error when running. Would you please help me review my code. Thanks in advance.

DichVu2TableViewCell.h

@class DichVu2TableViewCell;
//Change : NSObject to <NSObject> because XCode 6.3 has error.
@protocol DichVu2TableViewCellDelegate <NSObject>

-(void)changeCell:(DichVu2TableViewCell *)sender state:(NSString *)service package:(NSString *)package loaigoi:(NSString *)loai_goi;

@end

@interface DichVu2TableViewCell : UITableViewCell

@property (weak) id <DichVu2TableViewCellDelegate> delegate;

@end

DichVu2TableViewCell.m

@implementation DichVu2TableViewCell
….
- (void)someSwitchingEvent
{
    [self.delegate changeCell:self state:_service package:_package loaigoi:_loai_goi];
}
@end

DanhsachTableViewController.h

@interface DanhsachTableViewController : UITableViewController

@property (strong,nonatomic) NSString *loaitb;
@property (strong,nonatomic) NSString *type;
@property (strong,nonatomic) NSString *name;
@property NSMutableArray *pre_inuse_;
@property NSMutableArray *data_inuse_;
@property NSMutableArray *vas_inuse_;
@end

DanhsachTableViewController.m

#import "DichVu2TableViewCell.h"
//Change <DichVu2TableViewCellDelegate> to (DichVu2TableViewCellDelegate) because XCode 6.3 has error.
@interface DanhsachTableViewController (DichVu2TableViewCellDelegate)
@property (nonatomic) NSIndexPath *forUpdateIndexPath;
@end

@implementation DanhsachTableViewController{
    NSMutableArray *data;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    DichVu2TableViewCell *cell = (DichVu2TableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"dscell"];
    NSDictionary *dataCell =  data[indexPath.row];
    cell.service =  dataCell[@"service"];
    cell.package =  dataCell[@"package"];
    cell.loai_goi = dataCell[@"loai_goi"];
    cell.kieu_goi = dataCell[@"kieu_goi"];

    [cell.sudung setOn:NO animated:YES];
    cell.delegate = self;
//Change cellLocal —> cell because there are no cellLocal avaiable. And Program error when run to this row.
    [cell.sudung setOn:(self.forUpdateIndexPath == indexPath) animated:YES];

    return cell;
}

-(void)changeCell:(DichVu2TableViewCell *)sender state:(NSString *)service package:(NSString *)package loaigoi:(NSString *)loai_goi
{
//Add cellLocal —> cell because there are no cellLocal avaiable
    DichVu2TableViewCell *cellLocal = (DichVu2TableViewCell *)[self.tableView cellForRowAtIndexPath:self.forUpdateIndexPath];
    if ([service isEqualToString:cellLocal.service] && ![package isEqualToString:cellLocal.package] && [loai_goi isEqualToString:cellLocal.loai_goi]){
        // get the indexPath of the cell
        self.forUpdateIndexPath =  [self.tableView indexPathForCell:sender];
        // update the date source
        NSMutableDictionary *dataCell =  [data[self.forUpdateIndexPath.row] mutableCopy];
        [dataCell setObject:service forKey:@"service"];
        [dataCell setObject:package forKey:@"package"];
        [dataCell setObject:loai_goi forKey:@"loai_goi"];
        // you dont need the for-statement just reload the table
        [self.tableView reloadData];
        // then update the switch inside `- cellForRowAtIndexPath`
    }

}

Upvotes: 4

Views: 886

Answers (2)

0yeoj
0yeoj

Reputation: 4550

Have you tried logging self.superview.superview; ? are your sure is in type UIViewController?

if so:

Do not call [[DanhsachTableViewController alloc]

instead use the DanhsachTableViewController from your parentview

DanhsachTableViewController *tableview = (DanhsachTableViewController *)self.superview.superview;
[tableview changeCellState:_service package:_package loaigoi:_loai_goi];

This

DanhsachTableViewController *tableview = [[DanhsachTableViewController alloc] init]; assigns a new DanhsachTableViewController class and not the existing one.

Edit

USING protocol and delegate

When using delegate you dont need the self.superview.superview :)

UNDER DichVu2TableViewCell

@class DichVu2TableViewCell; 

@protocol DichVu2TableViewCellDelegate <NSObject>

-(void)changeCell:(DichVu2TableViewCell *)sender state:(NSString *)service package:(NSString *)package loaigoi:(NSString *)loai_goi;

@end

@interface DichVu2TableViewCell : UIViewController

@property (weak) id <DichVu2TableViewCellDelegate> delegate;

@end

@implementaion DichVu2TableViewCell

..

- (void)someSwitchingEvent
{
    [self.delegate changeCell:self state:_service package:_package loaigoi:_loai_goi];
}

@end

while

UNDER DanhsachTableViewController

// assuming you alreading imported the `DichVu2TableViewCell` like 
//
// #import "DichVu2TableViewCell.h"
//
// set the delegate

@interface DanhsachTableViewController () <DichVu2TableViewCellDelegate>

@property (nonatomic) NSIndexPath *forUpdateIndexPath;

@end

// then implement the method from the delegate under implementation file

@implementation DanhsachTableViewController
{
    NSMutableArray *data;
}

- (void)viewDidLoad 
{
    [super viewDidLoad];
    [self loadData];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    DichVu2TableViewCell *cell = (DichVu2TableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"dscell"];
    NSDictionary *dataCell =  data[indexPath.row];
    cell.service =  dataCell[@"service"];
    cell.package =  dataCell[@"package"];
    cell.loai_goi = dataCell[@"loai_goi"];

    // this is the magic .. :)
    //--
    cell.delegate = self;

    [cell.sudung setOn:(self.forUpdateIndexPath == indexPath) animated:YES];
    //--

    return cell;
}

-(void)changeCell:(DichVu2TableViewCell *)sender state:(NSString *)service package:(NSString *)package loaigoi:(NSString *)loai_goi
{
    // `self.forUpdateIndexPath` is declared as property

   if ([service isEqualToString:service] && ![package isEqualToString:package] && [loai_goi isEqualToString:loai_goi]){

        // get the indexPath of the cell
        self.forUpdateIndexPath =  [self.tableView indexPathForCell:sender];

        // update the date source
        NSMutableDictionary *dataCell =  [data[self.forUpdateIndexPath.row] mutableCopy];

        [dataCell setObject:service forKey:@"service"];
        [dataCell setObject:package forKey:@"package"];
        [dataCell setObject:loai_goi forKey:@"loai_goi"];

        // you dont need the for-statement just reload the table

        [self.tableView reloadData];

        // then the switch will be updated inside `- cellForRowAtIndexPath`
    }

}

Hope this is more helpful now.. :) Cheers...

Upvotes: 0

danialzahid94
danialzahid94

Reputation: 4203

A more efficient method would be to use custom delegates.

  1. You can declare a protocol in your UITableViewController class.
  2. Declare the changeCellState function in the protocol.
  3. Create a delegate property in the UITableViewCell class.
  4. Call the delegate method from the UITableViewCell class when the switch value is changed.
  5. The UITableViewController will itself receive the message, and the function will be called respectively.

Upvotes: 1

Related Questions