TableViewCellDelegate isnt being called - ios

I am trying to add item to basket in this files. I have custom table cell and linked it with IBOutlets in storyboard. Somehow debugger reaches the delegate method inside deletegating object, but doesnt go further to TableVC, where this method is conformed, and no logs are seen.
// SeatTableViewCell.h
#import <UIKit/UIKit.h>
#import "SeatTableViewCellDelegate.h"
#interface SeatTableViewCell : UITableViewCell
#property (nonatomic, assign) id<SeatTableViewCellDelegate> delegate;
#property (nonatomic, weak) IBOutlet UILabel *rowLabel;
#property (nonatomic, weak) IBOutlet UILabel *seatLabel;
#property (nonatomic, weak) IBOutlet UILabel *priceLabel;
#property (nonatomic, weak) IBOutlet UIImageView *addToBasketImageView;
#end
// SeatTableViewCell.m
#import "SeatTableViewCell.h"
#implementation SeatTableViewCell
#synthesize rowLabel, seatLabel, priceLabel, addToBasketImageView;
- (void)awakeFromNib {
[super awakeFromNib];
UITapGestureRecognizer *singleImageTap = [[UITapGestureRecognizer alloc] initWithTarget:
self action:#selector(addToBasketTapDetected:)];
singleImageTap.numberOfTapsRequired = 1;
[self.addToBasketImageView addGestureRecognizer:singleImageTap];
}
- (void)addToBasketTapDetected: (UIGestureRecognizer *)sender {
//HERE the debugger stops, after step into nothing happens
[self.delegate tableViewCell:self didSelectImageView:self.addToBasketImageView];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
// SeatTableViewCellDelegate.h
#protocol SeatTableViewCellDelegate <NSObject>
- (void)tableViewCell:(UITableViewCell *)cell didSelectImageView:(UIImageView *)imageView;
#end
// ChooseSeatTableViewController.h
#import <UIKit/UIKit.h>
#import "SeatGroup.h"
#import "SeatTableViewCellDelegate.h"
#interface ChooseSeatTableViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, SeatTableViewCellDelegate>
- (IBAction)onBackPressed:(id)sender;
- (IBAction)OnChooseSectorClicked:(id)sender;
-(void)reloadData:(SeatGroup *)selectedSeatGroup;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (nonatomic, strong) SeatGroup *seatGroup;
#property (nonatomic, strong) NSString* perfUUID;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableHeightConstraint;
#property (nonatomic, strong) NSMutableArray* seats;
#end
// ChooseSeatTableViewController.m
#import "ChooseSeatTableViewController.h"
#import "ConcertDescriptionViewController.h"
#import "SeatTableViewCell.h"
#interface ChooseSeatTableViewController ()
#property (nonatomic, strong) NSMutableArray *selectedIndexPathes;
#property (strong) Seat* currentSeat;
#end
#implementation ChooseSeatTableViewController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
int volume = self.seats.count;
return volume;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_currentSeat = [_seats objectAtIndex:indexPath.row];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"seatCell";
//todo try fix bug with dequing indexes
SeatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
Seat *cur = [_seats objectAtIndex:indexPath.row];
_currentSeat = cur;
cell.rowLabel.text = cur.rowNum;
cell.seatLabel.text = cur.seatNum;
NSArray* piecesOfPrice = [cur.price componentsSeparatedByString: #","];
if (piecesOfPrice.count > 1) {
cur.price = [piecesOfPrice objectAtIndex:0];
}
NSMutableString *prm = [cur.price mutableCopy];
[prm appendString:#" p"];
cell.priceLabel.text = prm;
[cell.addToBasketImageView setUserInteractionEnabled:YES];
if ([self.selectedIndexPathes containsObject:indexPath]) {
//set basket selected
NSString *thePath = [[NSBundle mainBundle] pathForResource:#"rectangle_21_copy_5" ofType:#"png"];
UIImage *priceBckgImg = [[UIImage alloc] initWithContentsOfFile:thePath];
cell.addToBasketImageView.image = priceBckgImg;
} else {
//set basket unselected
NSString *thePath = [[NSBundle mainBundle] pathForResource:#"rectangle_21_copy_6" ofType:#"png"];
UIImage *priceBckgImg = [[UIImage alloc] initWithContentsOfFile:thePath];
cell.addToBasketImageView.image = priceBckgImg;
}
return cell;
}
- (void)tableViewCell:(UITableViewCell *)cell didSelectImageView:(UIImageView *)imageView {
//HERE the debugger doesnt reach
NSLog(#"Hi, debugger in didSelectImageView");
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
if (![self.selectedIndexPathes containsObject:indexPath]) {
[self.selectedIndexPathes addObject:indexPath];
}
NSString *thePath = [[NSBundle mainBundle] pathForResource:#"rectangle_21_copy_5" ofType:#"png"];
UIImage *priceBckgImg = [[UIImage alloc] initWithContentsOfFile:thePath];
[imageView setImage:priceBckgImg];
[self.tableView reloadData];
}
..
Why my protocol isn being called?

You have to set your view controller as delegate:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"seatCell";
SeatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.delegate = self;
....
}

AlexInspired,
The only statement missing is in cellForRowAtIndexPath :)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"seatCell";
//todo try fix bug with dequing indexes
SeatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
Seat *cur = [_seats objectAtIndex:indexPath.row];
_currentSeat = cur;
cell.rowLabel.text = cur.rowNum;
cell.seatLabel.text = cur.seatNum;
cell.delegate = self;
....
return cell;
}

You didn't set delegate for tableview cell.
Set delegate and enjoy :) your problem is solved.
cell.delegate = self

you forget to set delegate to self. so in cellForRowAtIndexPath set delegate to self like,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"seatCell";
//todo try fix bug with dequing indexes
SeatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.delegate = self;
}
by this you are assigning current class object to cell class so you can able to call current class method from cell class.
:)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"seatCell";
//todo try fix bug with dequing indexes
SeatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.delegate=self;
.
.
.

write following code in CellforRowAtIndexPath method it will help for you
NSString *cellDdentifier = #"seatCell";
SeatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.delegate = self

Related

How to call a method from parent class to it's child class?

In my main viewcontroller there is a method like as below:
-(void)updateCartItem {
}
I want to call it into uitableviewcell class under a button action method:
- (IBAction)Cart:(id)sender {
[self updateCartItem];//like this you can call parent method which contain your VC.m file
}
please help me thanks in advance...
You can use a Delegate or a code block to do this, I will post both ways with examples for your clarification
Delegate Approach
1 - Declare your cell Delegate
Our example cell will be called CustomTableViewCell
#protocol CustomCellDelegate
-(void)executeAction;
#end
and add your delegate to your cell declaration, must be weak to avoid retain cycles
#property (weak) id<CustomCellDelegate> cellDelegate;
2 - Execute your delegate action in your Cell Action
- (IBAction)Cart:(id)sender {
[[self cellDelegate] executeAction];
}
3 - Make your UIViewController implement CustomCellDelegate of your CustomCell
#interface ViewController () <UITableViewDataSource,UITableViewDelegate,CustomCellDelegate>
-(void)executeAction
{
[self updateCartItem];
}
4 - Make your UIViewController as Delegate of your CustomCell adjusting your cellForRowAtIndexPath method
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomTableViewCell *cell = (CustomTableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
cell.cellDelegate = self;
return cell;
}
Full Code
CustomTableViewCell.h
#import <UIKit/UIKit.h>
#protocol CustomCellDelegate
-(void)executeAction;
#end
#interface CustomTableViewCell : UITableViewCell
#property (weak) id<CustomCellDelegate> cellDelegate;
#end
CustomTableViewCell.m
#import "CustomTableViewCell.h"
#implementation CustomTableViewCell
- (IBAction)Cart:(id)sender {
[[self cellDelegate] executeAction];
}
#end
ViewController.m
#import "ViewController.h"
#import "CustomTableViewCell.h"
#interface ViewController () <UITableViewDataSource,UITableViewDelegate,CustomCellDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[_tableView setDelegate:self];
[_tableView setDataSource:self];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomTableViewCell *cell = (CustomTableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
cell.cellDelegate = self;
return cell;
}
-(void)updateCartItem {
//Whatever you need to do here
}
-(void)executeAction
{
[self updateCartItem];
}
#end
Code Block Approach
1 - Declare your actionBlock in your Customcell
Our example cell will be called CustomCell
#property void(^actionBlock)(void);
2 - Execute your action block in your Cell Action
- (IBAction)Cart:(id)sender {
[self actionBlock];
}
3 - Setup your cell block action adjusting your cellForRowAtIndexPath method
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomTableViewCell *cell = (CustomTableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
__weak ViewController *weakSelf = self;
cell.actionBlock = ^{
[weakSelf updateCartItem];
};
return cell;
}
Full Code
CustomTableViewCell.h
#import <UIKit/UIKit.h>
#interface CustomTableViewCell : UITableViewCell
#property void(^actionBlock)(void);
#end
CustomTableViewCell.m
#import "CustomTableViewCell.h"
#implementation CustomTableViewCell
- (IBAction)Cart:(id)sender {
[self actionBlock];
}
#end
ViewController.m
#import "ViewController.h"
#import "CustomTableViewCell.h"
#interface ViewController () <UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[_tableView setDelegate:self];
[_tableView setDataSource:self];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell";
CustomTableViewCell *cell = (CustomTableViewCell*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath:indexPath];
__weak ViewController *weakSelf = self;
cell.actionBlock = ^{
[weakSelf updateCartItem];
};
return cell;
}
-(void)updateCartItem {
//Whatever you need to do here
}
#end

Can't set Custom UITableViewCell property - iOS

First of all I want to apologize for my bad english.
I'm having trouble to set the properties of my custom UITableViewCell (HistoricoCell).
When I try to set a property of my cell I get: Signal SIGABRT error:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Dequeue the cell.
HistoricoCell *cell = (HistoricoCell *)[self.tblHistorico dequeueReusableCellWithIdentifier:#"CellIdentifier" forIndexPath:indexPath];
// Fetch Item
NSDictionary *item = [self.dbManager.arrColumnNames objectAtIndex:indexPath.row];
// Configure Table View Cell
[cell.lblCodigo setText:[NSString stringWithFormat:#"%#", item[#"codigo"]]];
[cell.btnFavoritar addTarget:self action:#selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
I followed a lot of tutorials and questions on the web but I stil with my error.
Can someone help me?
My code:
HistoricoCell.h
#import <UIKit/UIKit.h>
#interface HistoricoCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *lblCodigo;
#property (weak, nonatomic) IBOutlet UIButton *btnFavoritar;
#end
SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tblHistorico;
SecondViewController.m
#import "SecondViewController.h"
#import "DBManager.h"
#import "HistoricoCell.h"
#interface SecondViewController ()
#property (nonatomic, strong) DBManager *dbManager;
#property (nonatomic, strong) NSArray *arrPeopleInfo;
-(void)loadData;
#end
#implementation SecondViewController
static NSString *CellIdentifier = #"CellIdentifier";
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Make self the delegate and datasource of the table view.
self.tblHistorico.delegate = self;
self.tblHistorico.dataSource = self;
// Initialize the dbManager property.
self.dbManager = [[DBManager alloc] initWithDatabaseFilename:#"bernoullidb.sql"];
[self.tblHistorico registerClass:[HistoricoCell class] forCellReuseIdentifier:#"CellIdentifier"];
[self loadData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)loadData{
// Form the query.
NSString *query = #"select * from tbHistorico";
// Get the results.
if (self.arrPeopleInfo != nil) {
self.arrPeopleInfo = nil;
}
self.arrPeopleInfo = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
// Reload the table view.
//[self.tblHistorico reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.arrPeopleInfo.count;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 60.0;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Dequeue the cell.
HistoricoCell *cell = (HistoricoCell *)[self.tblHistorico dequeueReusableCellWithIdentifier:#"CellIdentifier" forIndexPath:indexPath];
// Fetch Item
NSDictionary *item = [self.dbManager.arrColumnNames objectAtIndex:indexPath.row];
// Configure Table View Cell
[cell.lblCodigo setText:[NSString stringWithFormat:#"%#", item[#"codigo"]]];
[cell.btnFavoritar addTarget:self action:#selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (void)didTapButton:(id)sender {
NSLog(#"%s", __PRETTY_FUNCTION__);
}
#end
You should set cell indentifier "CellIdentifier" for your cell in File Inspector
Or register your nib file if you add cell with nib:
UINib *itemNib = [UINib nibWithNibName:#"yourCell" bundle:nil];
[self.tableView registerNib:itemNib forCellReuseIdentifier:#"yourCellReuseIndentifier"];
I think your problem is in your cell creation: you try to dequeue a cell if it exists (i.e. recycle a previously used cell). that is OK, but, especially when the TableView is displayed for the first time, no previously used cell for this table exists. So, you have to create one if the dequeueReusableCellWithIdentifier call return nil.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Dequeue the cell.
HistoricoCell *cell = (HistoricoCell *)[self.tblHistorico dequeueReusableCellWithIdentifier:#"HistoricoCellIdentifier" forIndexPath:indexPath];
if( cell == nil ) // no queuded cell to dequeue
{
// you have to create a fresh new one
cell = [HistoricoCell alloc] initWithStyle:<your cell style> reuseIdentifier:#"HistoricoCellIdentifier"];
}
// Fetch Item
NSDictionary *item = [self.dbManager.arrColumnNames objectAtIndex:indexPath.row];
// Configure Table View Cell
[cell.lblCodigo setText:[NSString stringWithFormat:#"%#", item[#"codigo"]]];
[cell.btnFavoritar addTarget:self action:#selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}

Subclass of UITableView indexPath nil

I'm trying to subclass a UITableView. However, I'm unable to get an indexPath that isn't nil. The tableView has custom cells.
Here is my TouchTableView.h
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h> //I brought this in because I'm saving audio files in my app
#import "SimpleTableCell.h"
#protocol myTableViewDelegate;
#interface TouchTableView : UITableView <UITableViewDelegate, UITableViewDataSource, AVAudioRecorderDelegate, AVAudioPlayerDelegate, UITextViewDelegate, UITextFieldDelegate, UIAlertViewDelegate>
#property (nonatomic, weak) id<myTableViewDelegate> myDelegate;
#property (strong, nonatomic) NSMutableArray *sortedFiles;
#property (strong, nonatomic) NSString *simpleTableIdentifier;
#property (strong, nonatomic) SimpleTableCell *cell;
#property BOOL inverted;
-(void)refreshTable;
#end
#protocol myTableViewDelegate <NSObject>
- (void)selectedFile:(TouchTableView *)tableView withURL: (NSURL *) tableViewURL IndexPath:(NSIndexPath *)indexPath;
-(void)didDelete:(TouchTableView *)tableView IndexPath:(NSIndexPath *)indexPath;
-(void)setSortedFile:(TouchTableView *)tableView;
#end
I attach a longpress like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//bring in your custom cell here
simpleTableIdentifier = #"SimpleTableCell";
cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell.textField setEnabled:NO];
//put in long press
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPress:)];
[longPressGesture setMinimumPressDuration:1.0];
[cell addGestureRecognizer:longPressGesture];
}
}
return cell;
}
Then I have the following method for when the longpress activates:
- (void)longPress:(UILongPressGestureRecognizer *)gesture
{
if (![cell.textField isEnabled]) {
// only when gesture was recognized, not when ended
if (gesture.state == UIGestureRecognizerStateBegan)
{
// get affected cell
cell = (SimpleTableCell *)[gesture view];
// get indexPath of cell
NSIndexPath *indexPath = [self indexPathForCell:cell];
[self selectRowAtIndexPath:indexPath animated:NO scrollPosition:0];
[cell.textField setEnabled:YES];
[cell.textField becomeFirstResponder];
}
}
}
In my viewController in viewDidLoad I have:
self.touchTableView = [[TouchTableView alloc] init];
[self.tableView setDelegate:self.touchTableView];
[self.tableView setDataSource:self.touchTableView];
self.touchTableView.myDelegate = self;
The problem is that the indexPath is always nil. You'll note that I'm calling self instead of self.tableView because self is the tableView. Is there a way to get the indexPath?
Sorry for the mess all. rmaddy was right. Ridiculous. The solution:
in my ViewController.h I set up:
#property (weak, nonatomic) IBOutlet TouchTableView *tableView;
Then I changed the last code in my example to
[self.tableView setDelegate:self.tableView];
[self.tableView setDataSource:self.tableView];
self.tableView.myDelegate = self;
[self.tableView refreshTable];
Now I'm getting the index path.

Select one row in each section of UITableView ios?

Scenario:
I have made 2 sections in one UITableView and the user needs to select a row in each section as shown in the screenshot below.
Expected Outcome:
1. User should be able to select a row in each section
Outcome right now:
1. After I have selected row in one section, and then when I select the row in second section, the first selection disappears.
Here is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Uncheck the previous checked row
long sec=indexPath.section;
if(sec==0){
if(self->checkedIndexPath)
{
UITableViewCell* uncheckCell = [tableView
cellForRowAtIndexPath:self->checkedIndexPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
if([self->checkedIndexPath isEqual:indexPath])
{
self->checkedIndexPath = nil;
}
else
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self->checkedIndexPath = indexPath;
}}
if(sec==1){
if(self->checkedIndexPath)
{
UITableViewCell* uncheckCell = [tableView
cellForRowAtIndexPath:self->checkedIndexPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
if([self->checkedIndexPath isEqual:indexPath])
{
self->checkedIndexPath = nil;
}
else
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self->checkedIndexPath = indexPath;
}
}
}
Help is appreciated.
This is the simplest way.
Finally i found a solution. It works for me, hope it will work for you.
declare these
#interface ViewController ()
{
int selectedsection;
NSMutableArray *selectedindex;
}
Replace didSelectRowAtIndexPath as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Uncheck the previous checked row
NSIndexPath *selectedIndexPath = [tableView indexPathForSelectedRow];
if(self.checkedIndexPath)
{
for (int i=0; i<[selectedindex count]; i++) {
NSIndexPath *temp= [selectedindex objectAtIndex:i];
if (temp.section==selectedIndexPath.section) {
UITableViewCell* uncheckCell = [tableView
cellForRowAtIndexPath:temp];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
}
NSInteger numb= [tableView numberOfRowsInSection:selectedIndexPath.section];
if (selectedsection==selectedIndexPath.section) {
UITableViewCell* uncheckCell = [tableView
cellForRowAtIndexPath:self.checkedIndexPath];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
}
if([self.checkedIndexPath isEqual:indexPath])
{
for (int i=0; i<[selectedindex count]; i++) {
NSIndexPath *temp= [selectedindex objectAtIndex:i];
if (temp.section==selectedIndexPath.section) {
UITableViewCell* uncheckCell = [tableView
cellForRowAtIndexPath:temp];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
}
self.checkedIndexPath = nil;
}
else
{
for (int i=0; i<[selectedindex count]; i++) {
NSIndexPath *temp= [selectedindex objectAtIndex:i];
if (temp.section==selectedIndexPath.section) {
UITableViewCell* uncheckCell = [tableView
cellForRowAtIndexPath:temp];
uncheckCell.accessoryType = UITableViewCellAccessoryNone;
}
}
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
self.checkedIndexPath = indexPath;
[selectedindex addObject:indexPath];
selectedsection=indexPath.section;
NSLog(#"check");
}
}
You can enable the multiple selection in the tableview:
self.tableView.allowsMultipleSelection = YES;
I wrote a sample code where a compound datasource holds datasource objects for each section. Sounds complicated but actually provides an easy to extend architecture. And keeps your view controller small.
The advantages of this approach:
Small ViewController
ViewController set ups view and handles user interaction — as it should be in MVC
Reusable datasources
by using different datasources per section easy to customize cells for each section
the base datasource architecture
This provides easy extension and is simple to reuse.
#import UIKit;
#interface ComoundTableViewDataSource : NSObject
#property (nonatomic,strong, readonly) NSMutableDictionary *internalDictionary;
-(void) setDataSource:(id<UITableViewDataSource>)dataSource forSection:(NSUInteger)section;
-(instancetype)initWithTableView:(UITableView *)tableView;
#end
#import "ComoundTableViewDataSource.h"
#interface ComoundTableViewDataSource () <UITableViewDataSource>
#property (nonatomic,strong, readwrite) NSMutableDictionary *internalDictionary;
#property (nonatomic, weak) UITableView *tableView;
#end
#implementation ComoundTableViewDataSource
-(instancetype)initWithTableView:(UITableView *)tableView
{
self = [super init];
if (self) {
_tableView = tableView;
tableView.dataSource = self;
_internalDictionary = [#{} mutableCopy];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
}
return self;
}
-(void)setDataSource:(id<UITableViewDataSource>)dataSource forSection:(NSUInteger)section
{
self.internalDictionary[#(section)] = dataSource;
[self.tableView reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.internalDictionary allKeys] count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id<UITableViewDataSource> sectionDataSource = self.internalDictionary[#(section)];
return [sectionDataSource tableView:tableView numberOfRowsInSection:section];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
id<UITableViewDataSource> sectionDataSource = self.internalDictionary[#(indexPath.section)];
return [sectionDataSource tableView:tableView cellForRowAtIndexPath:indexPath];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
id<UITableViewDataSource> sectionDataSource = self.internalDictionary[#(section)];
return [sectionDataSource tableView:tableView titleForHeaderInSection:section];
}
#end
#import UIKit;
#interface SingleSectionDataSource : NSObject <UITableViewDataSource>
#property (nonatomic, strong, readonly) NSArray *array;
#property (nonatomic, strong, readonly) UITableView *tableView;
- (instancetype)initWithArray:(NSArray *)array;
#end
#import "SingleSectionDataSource.h"
#interface SingleSectionDataSource ()
#property (nonatomic, strong, readwrite) NSArray *array;
#property (nonatomic, strong, readwrite) UITableView *tableView;
#end
#implementation SingleSectionDataSource
- (instancetype)initWithArray:(NSArray *)array
{
self = [super init];
if (self) {
self.array = array;
}
return self;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
self.tableView = tableView;
return self.array.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.array[indexPath.row];
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [#(section) stringValue];
}
#end
the selection datasource architecture
We extend the classes from above to allow one selection per section
#import "ComoundTableViewDataSource.h"
#interface OnSelectionPerSectionComoundTableViewDataSource : ComoundTableViewDataSource
-(void)selectedCellAtIndexPath:(NSIndexPath *)indexPath;
#end
#import "OnSelectionPerSectionComoundTableViewDataSource.h"
#import "SingleSelectionSingleSectionDataSource.h"
#implementation OnSelectionPerSectionComoundTableViewDataSource
-(instancetype)initWithTableView:(UITableView *)tableView
{
self = [super initWithTableView:tableView];
if(self){
[tableView setAllowsMultipleSelection:YES];
}
return self;
}
-(void)selectedCellAtIndexPath:(NSIndexPath *)indexPath
{
SingleSelectionSingleSectionDataSource *sectionDataSource = self.internalDictionary[#(indexPath.section)];
[sectionDataSource selectedCellAtIndexPath:indexPath];
}
#end
View Controller Implementation
As promised, a very slim view controller:
#interface ViewController () <UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (nonatomic, strong) OnSelectionPerSectionComoundTableViewDataSource *tableViewDataSource;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableViewDataSource = [[OnSelectionPerSectionComoundTableViewDataSource alloc] initWithTableView:self.tableView];
self.tableView.delegate = self;
[self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:#[#"Hallo", #"Welt"]] forSection:0];
[self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:#[#"Hello", #"World", #"!"]] forSection:1];
[self.tableViewDataSource setDataSource:[[SingleSelectionSingleSectionDataSource alloc] initWithArray:#[#"Hola", #"Mundo", #"!", #"¿Que tal?"]] forSection:2];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableViewDataSource selectedCellAtIndexPath:indexPath];
}
#end
You will want to add methods to the datasources to get the selected rows.
get the example: https://github.com/vikingosegundo/CompoundDatasourceExample
Note This code has a cell reuse issue. It is fixed on GitHub.

How to change the text in several labels when a special table view cell is pressed?

Here are the ViewControllers again.
Here is my ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (copy, nonatomic) NSDictionary *firstTableView;
#property (copy, nonatomic) NSArray *firstTableViewKey;
#property (weak, nonatomic) IBOutlet UILabel *norskLabel;
#property (weak, nonatomic) IBOutlet UILabel *infinitivLabel;
#property (weak, nonatomic) IBOutlet UILabel *presensLabel;
#property (weak, nonatomic) IBOutlet UILabel *preteritumLabel;
#property (weak, nonatomic) IBOutlet UILabel *perfektumLabel;
#end
Here is my ViewController.m:
#import "ViewController.h"
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *tableView = (id)[self.view viewWithTag:1];
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:SectionsTableIdentifier];
NSString *path = [[NSBundle mainBundle] pathForResource:#"SterkeVerb" ofType:#"plist"];
self.firstTableView = [NSDictionary dictionaryWithContentsOfFile:path];
self.firstTableViewKey = [[self.firstTableView allKeys] sortedArrayUsingSelector:#selector(compare:)];
tableView.backgroundColor = [UIColor clearColor];
tableView.opaque = NO;
tableView.backgroundView = nil;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return [self.firstTableViewKey count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSString *key = self.firstTableViewKey[section];
NSArray *nameSection = self.firstTableView[key];
return [nameSection count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
return self.firstTableViewKey[section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
NSString *key = self.firstTableViewKey[indexPath.section];
NSArray *nameSection = self.firstTableView[key];
cell.textLabel.text = nameSection[indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0){
_norskLabel.text = #"å bake";
_infinitivLabel.text = #"zu backen";
_presensLabel.text = #"bäckt/backt";
_preteritumLabel.text = #"backte";
_perfektumLabel.text = #"hat gebacken";
}
else if (indexPath.row == 1){
_norskLabel.text = #"å motta";
_infinitivLabel.text = #"zu empfangen";
_presensLabel.text = #"empfängt";
_preteritumLabel.text = #"empfing";
_perfektumLabel.text = #"hat empfangen";
}
}
Ok, so i have my table view devided into sections(A-Z) and when i filled in the code it worked perfectly for the first section. BUT, when i pressed one of the cells in the next section, it showed the same information as the first cell in the first section. WHY?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0){
_norskLabel.text = #"å bake";
_infinitivLabel.text = #"zu backen";
_presensLabel.text = #"bäckt";
_preteritumLabel.text = #"backte";
_perfektumLabel.text = #"hat gebacken";
else if (indexPath.row == 1){
_norskLabel.text = #"å begynne";
_infinitivLabel.text = #"zu beginnen";
_presensLabel.text = #"beginnt";
_preteritumLabel.text = #"begann";
_perfektumLabel.text = #"hat begonnen";
}
}
If you set the text in tableview:didSelectRowAtIndexPath: it will just get overwritten when tableview:cellForRowAtIndexPath: is called
Inside tableview:didSelectRowAtIndexPath:, you need to access the data driving the table and change it at its source.
NSString *key = self.firstTableViewKey[indexPath.section];
NSArray *nameSection = self.firstTableView[key];
nameSection[indexPath.row] = #"New Value";

Resources