I am making an app in which i am using buttons in the form of checkboxes in uitableview cell.i am changing images on that checkbox select and unselect state. now i want that when i click on another button then all the cells of table view will be select and image of all the checkboxes of cells will changed? how it can done below is my sample code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.lblArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *tableviewidentifier = #"cell";
TablecellTableViewCell *cell= [self.tblvie dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[TablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
cell.lblImage.layer.cornerRadius=3.0f;
cell.lblImage.layer.borderWidth=1.0f;
cell.backgroundColor=[UIColor colorWithRed:(245/255.0) green:(245/255.0) blue:(245/255.0) alpha:1];
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]])
{
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"check_box_ok.png"]
forState:UIControlStateNormal];
}
else
{
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"uncheck.png"]
forState:UIControlStateNormal];
}
cell.buttonCheckbox.tag=indexPath.row;
[cell.buttonCheckbox addTarget:self action:#selector(checkButton:) forControlEvents:UIControlEventTouchUpInside];
cell.lblText.text=[self.lblArray objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)checkButton:(UIButton *)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tblvie];
NSIndexPath *indexPath = [self.tblvie indexPathForRowAtPoint:buttonPosition];
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]]) {
[self.checkimageArray removeObject:[self.lblArray objectAtIndex:indexPath.row]];
self.titleLabel.text=#"";
}
else {
[self.checkimageArray addObject:[self.lblArray objectAtIndex:indexPath.row]];
self.titleLabel.text=[self.lblArray objectAtIndex:sender.tag];
}
[self.tblvie reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationFade];
}
and here is my button in which i click then all the cells of tableview will select and images of all the cells will changed but it is not working
- (IBAction)selectbtns:(id)sender {
static NSString *tableviewidentifier = #"cell";
TablecellTableViewCell *cell= [self.tblvie dequeueReusableCellWithIdentifier:tableviewidentifier];
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"check_box_ok.png"]
forState:UIControlStateNormal];
}
NSMutableArray *totalcheckmarkArray; //add on NSMutablearray in globally
- (void)viewDidLoad {
totalcheckmarkArray =[[NSMutableArray alloc]init];
for (int i=0; i<[self.lblArray count]; i++) // Number of Rows count
{
[self.totalcheckmarkArray addObject:#"NO"];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tableviewidentifier = #"cell";
TablecellTableViewCell *cell= [self.tblvie dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[TablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
cell.lblImage.layer.cornerRadius=3.0f;
cell.lblImage.layer.borderWidth=1.0f;
if(![[self.totalcheckmarkArray objectAtIndex:indexPath.row] isEqualToString:#"NO"])
{
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"check_box_ok.png"] forState:UIControlStateNormal];
}
else if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]])
{
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"check_box_ok.png"] forState:UIControlStateNormal];
}
else
{
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
}
cell.buttonCheckbox.tag=indexPath.row;
[cell.buttonCheckbox addTarget:self action:#selector(checkButton:) forControlEvents:UIControlEventTouchUpInside];
cell.lblText.text=[self.lblArray objectAtIndex:indexPath.row];
return cell;
}
selectAll Checkbox
- (IBAction)selectbtns:(id)sender {
for (int i=0; i<[self.lblArray count]; i++)
{
[totalcheckmarkArray replaceObjectAtIndex:i withObject:#"YES"];
}
[self.tblvie reloadData];
}
DeselectAll Checkbox
-(IBAction)deselectall_btnclick:(id)sender
{
for (int i=0; i<[self.lblArray count]; i++)
{
[totalcheckmarkArray replaceObjectAtIndex:i withObject:#"NO"];
}
[self.tblvie reloadData];
}
I can think of two possible solutions. If the following line works in cellForRowAtIndexPath:
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]]) {
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"check_box_ok.png"] forState:UIControlStateNormal];
}
Then just add all the images to self.checkimageAray and then reload the table through [self.tblvie reloadData].
If there is a reason you don't want to reload the table, you could do the following, which will loop through all the cells in the table and execute the changes to each cell:
for (int section = 0; section < [self.tblvie numberOfSections]; section++) {
for (int row = 0; row < [self.tblvie numberOfRowsInSection:section]; row++) {
NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
TablecellTableViewCell *cell= [self.tblvie cellForRowAtIndexPath:cellPath];
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"check_box_ok.png"]
forState:UIControlStateNormal];
}
}
I tend to iterate over every cell when I wish to make a change with an animation. If say you want to animate the checking of the box, the simplest way would be to place the animation block in the iteration of the cells.
If you wish to then unselect a cell, you could do the following:
for (int section = 0; section < [self.tblvie numberOfSections]; section++) {
for (int row = 0; row < [self.tblvie numberOfRowsInSection:section]; row++) {
NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
TablecellTableViewCell *cell= [self.tblvie cellForRowAtIndexPath:cellPath];
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"uncheck.png"]
forState:UIControlStateNormal];
}
}
Please note that this is not changing your checkimageArray. While the cells are being displayed as selected, all of the images are not in your checkimageArray, and of corse with my solution for unselecting the cell, the images will not be removed from the checkimageArray either.
I would suggest adding all the objects from self.lblArray to checkimageArray where you place the code to set the cells highlighted and remove all objects from checkimageArray when you deselect them all. An example of how to add all images to the array is show in the other answer bellow.
You can do .
- (IBAction)selectbtns:(id)sender
{
self.checkimageArray = [NSArray arrayWithArray:self.lblArray];
[self.tableView reloadData];
}
Related
I currently have 2 categories (cat, dog) in 1 UITableView.
This is the illustration:
The cat and dog button are part of the UITableView they are in the header section.
they act as a separator for both categories.
what i'm trying to achieve is when i click the cat button, the list under the cat button should collapse and the dog button should re - adjust it's position.
When i click again the cat button, the list should expand.
what i currently have is :
NSUInteger indexes = (unsigned long)filteredList.count;
for (int i = 0 ; i <= indexes - 1 ; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[self.accountBalanceTableView cellForRowAtIndexPath:indexPath].hidden = YES;
}
It hides all of my cat list but the dog button is not adjusting it's position where it just leaves a huge amount of white space in the screen.
There are two possibilities you can do this.
Change the height of the rows in the section you want to hide.
Return 0 for the rows in the section you want to hide.
you can use two cell(maincell,subcell)in your table and put this code in cell for row at indexpath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == _tblDispChapters) {
if(indexPath.row == 0){
TVCDispChapters *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
//Accuracy
int acu;
if ([[marrParentChapters objectAtIndex:indexPath.section]valueForKey:#"acuracy"]==[NSNull null] ) {
NSLog(#"%#",[[marrParentChapters objectAtIndex:indexPath.section]valueForKey:#"acuracy"]);
acu=0;
}
else
{
acu=[[[marrParentChapters objectAtIndex:indexPath.section]valueForKey:#"acuracy"] intValue];
NSLog(#"%d",acu);
}
cell.lbl_acu.text=[NSString stringWithFormat:#"Accuracy %d%%",acu];
[cell.pro_cell_chapt.layer setCornerRadius:cell.pro_cell_chapt.frame.size.height/2];
cell.pro_cell_chapt.clipsToBounds = true;
[cell.pro_cell_chapt setTransform:CGAffineTransformMakeScale(1.0f, 2.0f)];
cell.pro_cell_chapt.progress = acu/100.0;
cell.pro_cell_chapt.trackTintColor = [UIColor colorWithHex:0xDDDDDD];
cell.pro_cell_chapt.progressTintColor = [UIColor colorWithHex:0xEF9430];
cell.lblChepterName.text = [[marrParentChapters objectAtIndex:indexPath.section]valueForKey:#"ChapterName"];
[cell.btn_sel_allchptr setTag:indexPath.section];
[cell.btn_sel_allchptr addTarget:self action:#selector(checkBoxClicked:)forControlEvents:UIControlEventTouchUpInside];
if ([[_marrHideShowSection objectAtIndex:indexPath.section] boolValue]){
[cell.imgArrow setImage:[UIImage imageNamed:#"up-arrow1"]];
}else{
[cell.imgArrow setImage:[UIImage imageNamed:#"down-arrow1"]];
}
if ([[_marrAllChapter objectAtIndex:indexPath.section] boolValue]){
[cell.img_cpt_select setImage:[UIImage imageNamed:#"checkbox-selected1"]];
}else{
[cell.img_cpt_select setImage:[UIImage imageNamed:#"checkbox-unselected1"]];
}
return cell;
}else{
TVCDispChapters *cell = [tableView dequeueReusableCellWithIdentifier:#"sub_Cell" forIndexPath:indexPath];
cell.lblSubChapterName.text = [[[marrSubChapters objectAtIndex:indexPath.section] objectAtIndex:indexPath.row-1]valueForKey:#"ChapterName"];
if ([[[_marrSelectionSection objectAtIndex:indexPath.section] objectAtIndex:indexPath.row-1] boolValue])
{
[cell.imgSelection setImage:[UIImage imageNamed:#"checkbox-selected1"]];
}else{
[cell.imgSelection setImage:[UIImage imageNamed:#"checkbox-unselected1"]];
}
return cell;
}
}else{
QuestionTypeTVC *cell1 = [tableView dequeueReusableCellWithIdentifier:#"CellQuesType" forIndexPath:indexPath];
if ([_marrSelectedQuestionypeID containsObject:[[_marrQuestiontype objectAtIndex:indexPath.row] valueForKey:#"QuestionTypeID"]]){
cell1.imgSelection.image = [UIImage imageNamed:#"checkbox-selected1"];
}else{
cell1.imgSelection.image = [UIImage imageNamed:#"checkbox-unselected1"];
}
cell1.lblQuesType.text=#"1";
return cell1;
}
}
I am having custom-cell in which i put the UIButton as the CheckBox.
I want the array of selected checkBox indexPath in ViewController.
I am trying to set the UIButton Action event into the ViewController but it is not accessible. Here is my Code,
-(UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCellSaveSearchTableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:#"SaveSearchCell"];
if(!cell)
{
cell = [[[NSBundle mainBundle]loadNibNamed:#"CustomTableViewCellSaveSearchTableViewCell" owner:self options:nil]objectAtIndex:0];
}
[self setText:cell];
[cell.btnDelete addTarget:self action:#selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
cell.btnDelete.tag = indexPath.row;
return cell;
}
-(void)btnClick : (UIButton *)btn
{
// I Can't accaes this method.
}
How can i get this.
UITableViewCells have a state of their own to reflect if they are selected or not. You don't need a button in the cells (it is discouraged for UX reasons anyway). Check here for a tutorial.
Do according to these three floowing method.
- (void)viewDidLoad {
[super viewDidLoad];
chekMarkArray = [[NSMutableArray alloc]init];
int totalData = 10;
chekMarkArray=[[NSMutableArray alloc] initWithCapacity:totalData];
for (int i=0; i<totalData; i++) {
[chekMarkArray addObject:#(0)];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIButton *testButton;
if (cell == nil ||1) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
testButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
testButton.frame = CGRectMake(100, 5,25, 25);
testButton.tag = indexPath.row;
BOOL selectindex = [[chekMarkArray objectAtIndex:indexPath.row] boolValue];
if (!selectindex) {
testButton.backgroundColor = [UIColor greenColor];
}else{
testButton.backgroundColor = [UIColor redColor];
}
[testButton addTarget:self action:#selector(DropDownPressed:) forControlEvents:UIControlEventTouchDown];
[cell addSubview:testButton];
}
return cell;
}
checked button action
-(void)btnClick : (UIButton *)btn
{
UIButton *button = (UIButton*)sender;
BOOL currentStatus = [[chekMarkArray objectAtIndex:button.tag] boolValue];
//deselect all selection
for (int i=0;i<chekMarkArray.count;i++) {
[chekMarkArray replaceObjectAtIndex:i withObject:#(0)];//comment this line for multiple selected button
}
//select current button
[chekMarkArray replaceObjectAtIndex:button.tag withObject:#(!currentStatus)];
[self.tableView reloadData];
}
You may use this code instead of button
first Alloc NsmutableArray in ViewDidLoad
and put an Button outside Tableview to complete your action.
then add
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedRowsArray addObject:[arrShareTickets objectAtIndex:indexPath.row]];
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedRowsArray removeObject:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I am having a list displaying a name and a button titled as "Follow". When I tap on the button title should change to "UnFollow". If I tap on the button again the title should again change to "Follow". This is working fine, but when I am scrolling the table the title of the other cells are also changing due to cell reuse.
The code is as follows:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"AuthorsListCell";
AuthorsListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
dic_eachAuthor = [[_arr_authors objectAtIndex:indexPath.row] mutableCopy];
cell.lbl_authorName.text = [dic_eachAuthor objectForKey:#"name"];
cell.btn_followOrUnfollow.tag = indexPath.row;
if([dic_eachAuthor valueForKey:#"follow"]){
[cell.btn_followOrUnfollow setTitle:#"UnFollow" forState:UIControlStateNormal];
}
else{
[cell.btn_followOrUnfollow setTitle:#"Follow" forState:UIControlStateNormal];
}
// action button method declarations
[cell.btn_followOrUnfollow addTarget:self action:#selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
-(void)followOrUnfollow:(UIButton *)sender
{
if ([sender.titleLabel.text isEqualToString:#"Follow"]) {
[sender setTitle:#"UnFollow" forState:UIControlStateNormal];
[dic_eachAuthor setValue:#"1" forKey:#"follow"];
}
else if ([sender.titleLabel.text isEqualToString:#"UnFollow"]) {
[sender setTitle:#"Follow" forState:UIControlStateNormal];
[dic_eachAuthor setValue:nil forKey:#"follow"];
}
}
Please suggest something to prevent the cell reuse.
Add this condition in followOrUnfollow in cellForRowAtIndexPath also
if ([sender.titleLabel.text isEqualToString:#"Follow"]) {
[sender setTitle:#"UnFollow" forState:UIControlStateNormal];
}
else if ([sender.titleLabel.text isEqualToString:#"UnFollow"]) {
[sender setTitle:#"Follow" forState:UIControlStateNormal];
}
Store follow/unfollow state information within datasource.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"CellIdentifier";
ListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
cell.lbl_authorName.text = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:#"name"];
cell.btn_followOrUnfollow.tag = indexPath.row;
// action button method declarations
[cell.btn_followOrUnfollow addTarget:self action:#selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
NSString *btnTitle = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:#"userFollowUnfollow"];
[sender setTitle:btnTitle forState:UIControlStateNormal];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
-(void)followOrUnfollow:(UIButton *)sender
{
if ([sender.titleLabel.text isEqualToString:#"Follow"]) {
[sender setTitle:#"UnFollow" forState:UIControlStateNormal];
}
else if ([sender.titleLabel.text isEqualToString:#"UnFollow"]) {
[sender setTitle:#"Follow" forState:UIControlStateNormal];
}
[[_arr_authors objectAtIndex:sender.tag] setValue:sender.titleLabel.text forKey:#"userFollowUnfollow"];
}
When you originally populate the table row, you do it from an array here cell.lbl_authorName.text = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:#"name"];. The problem is that you don't populate the follow or unfollow information from this array. So all you are doing is toggling a button and there is no saving of the state of that button. What you need to do is modify the array to have a place to save the follow/unfollow state. Then populate the state in the table cell from this array. Then when you call followOrUnfollow: you need to modify the state in the array.
When the cell gets reused it goes and checks with the original array to populate it, populate the follow from the array and you will be set.
Edited to add some code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"CellIdentifier";
ListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.lbl_authorName.text = [[_arr_authors objectAtIndex:indexPath.row] objectForKey:#"name"];
cell.btn_followOrUnfollow.tag = indexPath.row;
if([[_arr_authors objectAtIndex:indexPath.row] valueForKey:#"follow"]){
[cell.btn_followOrUnfollow setTitle:#"UnFollow" forState:UIControlStateNormal];
else{
[cell.btn_followOrUnfollow setTitle:#"Follow" forState:UIControlStateNormal];
}
// action button method declarations
[cell.btn_followOrUnfollow addTarget:self action:#selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
-(void)followOrUnfollow:(UIButton *)sender
{
if ([sender.titleLabel.text isEqualToString:#"Follow"]) {
[sender setTitle:#"UnFollow" forState:UIControlStateNormal];
[[_arr_authors objectAtIndex:sender.tag] setValue:1 forKey:#"follow"]
}
else if ([sender.titleLabel.text isEqualToString:#"UnFollow"]) {
[sender setTitle:#"Follow" forState:UIControlStateNormal];
[[_arr_authors objectAtIndex:sender.tag] setValue:0 forKey:#"follow"]
}
}
I am not at my normal machine, so the syntax is probably off, but you should get the idea. Also note you will have to add the follow property to _arr_authors
You are missing something here, try this :
-(void)followOrUnfollow:(UIButton *)sender
{
NSDictionary *dict = (NSDictionary *) _arr_authors[sender tag];
if ([[dict objectForKey:#"name"] isEqualToString:#"Follow"])
{
[sender setTitle:#"UnFollow" forState:UIControlStateNormal];
}
else if ([[dict objectForKey:#"name"] isEqualToString:#"UnFollow"])
{
[sender setTitle:#"Follow" forState:UIControlStateNormal];
}
}
You are cells are reused so please implement this method in AuthorsListTableViewCell:
-(void) prepareForReuse{
[super prepareForReuse];
[self.btn_followOrUnfollow setTitle:#"Follow" forState:UIControlStateNormal];
}
// if the cell is reusable (has a reuse identifier), this is called just before the cell is returned from the table view method dequeueReusableCellWithIdentifier:. If you override, you MUST call super.
And set the correct default value to the cell.
I also recommend to implement this way:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"AuthorsListCell";
AuthorsListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
cell.lbl_authorName.text = [dic_eachAuthor objectForKey:#"name"];
cell.btn_followOrUnfollow.tag = indexPath.row;
[cell.btn_followOrUnfollow setTitle:#"Follow forState:UIControlStateNormal];
[cell.btn_followOrUnfollow setTitle:#"UnFollow" forState:UIControlStateSelected];
if([dic_eachAuthor valueForKey:#"follow"]){
cell.btn_followOrUnfollow.selected = YES;
} else{
cell.btn_followorUnfollow.selected = NO;
}
// action button method declarations
[cell.btn_followOrUnfollow addTarget:self action:#selector(followOrUnfollow:) forControlEvents:UIControlEventTouchUpInside];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
-(void)followOrUnfollow:(UIButton *)sender
{
sender.selected = !sender.selected;
if ([sender.titleLabel.text isEqualToString:#"Follow"]) {
[dic_eachAuthor setValue:#"1" forKey:#"follow"];
}
else if ([sender.titleLabel.text isEqualToString:#"UnFollow"]) {
[dic_eachAuthor setValue:nil forKey:#"follow"];
}
}
In AuthorsListTableViewCell
-(void) prepareForReuse{
[super prepareForReuse];
self.btn_followOrUnfollow.selected = NO;
}
I am making an app in which i am using in the form of checkboxes. i want to show count of checkboxes in text label i am trying but could not find possible solution.. here is my project link https://www.dropbox.com/s/iu8fdz4y0ps4xye/checkboxwithTableview%202.zip?dl=0 kindly review it..
Below is my sample code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *tableviewidentifier = #"cell";
TablecellTableViewCell *cell= [self.tblvie dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[TablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}
cell.lblImage.layer.cornerRadius=3.0f;
cell.lblImage.layer.borderWidth=1.0f;
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]])
{
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
// [cell.buttonCheckbox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
else
{
//[cell.buttonCheckbox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
[cell.buttonCheckbox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
}
cell.buttonCheckbox.tag=indexPath.row;
[cell.buttonCheckbox addTarget:self action:#selector(checkButton:) forControlEvents:UIControlEventTouchUpInside];
cell.lblText.text=[self.lblArray objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)checkButton:(UIButton *)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tblvie];
NSIndexPath *indexPath = [self.tblvie indexPathForRowAtPoint:buttonPosition];
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]]) {
[self.checkimageArray removeObject:[self.lblArray objectAtIndex:indexPath.row]];
self.titleLabel.text=#"";
}
else {
[self.checkimageArray addObject:[self.lblArray objectAtIndex:indexPath.row]];
NSArray *arr=[self.tblvie indexPathsForSelectedRows];// here i am declaring an array but array is coming nil
self.titleLabel.text=[self.lblArray objectAtIndex:indexPath.row];
}
[self.tblvie reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationFade];
}
Add Int variable in .h int checkBoxesCount;
Initialize it in ViewDidLoad like checkBoxesCount = 0;
Than Update your method like below
-(IBAction)checkButton:(UIButton *)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tblvie];
NSIndexPath *indexPath = [self.tblvie indexPathForRowAtPoint:buttonPosition];
if ([self.checkimageArray containsObject:[self.lblArray objectAtIndex:indexPath.row]]) {
[self.checkimageArray removeObject:[self.lblArray objectAtIndex:indexPath.row]];
checkBoxesCount = checkBoxesCount - 1;
self.titleLabel.text=[NSString stringWithFormat:#"Count %d",checkBoxesCount];
}
else {
[self.checkimageArray addObject:[self.lblArray objectAtIndex:indexPath.row]];
// self.titleLabel.text=[self.lblArray objectAtIndex:sender.tag];
checkBoxesCount = checkBoxesCount + 1;
self.titleLabel.text=[NSString stringWithFormat:#"Count %d",checkBoxesCount];
}
[self.tblvie reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation: UITableViewRowAnimationFade];
}
Problem resolved. I tested same on my end.
I have two sections in my tableview(iOS), where the first one is for the "favorites" rows. If you select the accessoryView it should add/remove the selected object in the "objects" array to/from "favs" array depending if the object already exist in the section.
The method I wrote almost works, but when I add a second row, or the same to remove it in favorites, the app crashes with this error:
Terminating app due to uncaught exception NSRangeException', reason: *** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]
The problem is that the index of the object in the corresponding arrays is not the same so I can't really figure out how to make this work properly.
Here's some code:
-(void)addToFavs:(id)sender{
UITapGestureRecognizer *gesture = (UITapGestureRecognizer *) sender;
NSLog(#"Tag = %d", gesture.view.tag);
//if favorite section is empty
if ([self.favs isEqualToArray:[#[]mutableCopy]]) {
NSLog(#"adding favorite");
[self.favs addObject:[self.objects objectAtIndex:gesture.view.tag]];
[self.subtitlesFavs addObject:[self.subtitles objectAtIndex:gesture.view.tag]];
[self.iconsFavs addObject:[self.icons objectAtIndex:gesture.view.tag]];
}
//if selected row already exist in favorites array <--HERE IS THE PROBLEM (I THINK)
else if([[self.objects objectAtIndex:gesture.view.tag] isEqualToString:[self.favs objectAtIndex:gesture.view.tag]]){
NSLog(#"removing favorite");
[self.favs removeObjectAtIndex:gesture.view.tag];
[self.subtitlesFavs removeObjectAtIndex:gesture.view.tag];
[self.iconsFavs removeObjectAtIndex:gesture.view.tag];
}else{
NSLog(#"adding favorite");
[self.favs addObject:[self.objects objectAtIndex:gesture.view.tag]];
[self.subtitlesFavs addObject:[self.subtitles objectAtIndex:gesture.view.tag]];
[self.iconsFavs addObject:[self.icons objectAtIndex:gesture.view.tag]];
}
[self.tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// left image
UIImageView *image=[[UIImageView alloc] initWithFrame:CGRectMake(7, 7, 30, 30)];
[image.layer setCornerRadius:image.frame.size.width/2];
[image setClipsToBounds:YES];
if(indexPath.section==0){
image.image=[UIImage imageNamed:[self.iconsFavs objectAtIndex:indexPath.row]];
}else{
image.image=[UIImage imageNamed:[self.icons objectAtIndex:indexPath.row]];
}
//fav image
UIImageView *fav = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"favorites.png"]];
[fav setFrame:CGRectMake(0, 0, 25, 25)];
[fav setClipsToBounds:YES];
if(!indexPath.section==0) {
fav.image=[UIImage imageNamed:#"unfavorites"];
}
//cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell){
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text=self.objects[indexPath.row];
cell.detailTextLabel.text =self.subtitles[indexPath.row];
[cell.contentView addSubview:image];
cell.accessoryView = fav;
//Favorites
cell.accessoryView.userInteractionEnabled = YES;
cell.accessoryView.tag = indexPath.row;
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(addToFavs:)];
tapped.numberOfTapsRequired = 1;
[cell.accessoryView addGestureRecognizer:tapped];
//favorites section contents
if (indexPath.section == 0)
{
cell.textLabel.text=self.favs[indexPath.row];
[cell.contentView addSubview:image];
cell.detailTextLabel.text =self.subtitlesFavs[indexPath.row];
}
}
return cell;
}
Update 1
I edited my code with "isEqualToString" in the if-condition but it still doesn't work to remove them...
Quite similar to what you have but try this anyways:
this be the -cellForRowAtIndexPath: method --
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
cell.detailTextLabel.textColor = [UIColor lightGrayColor];
//following commented line not needed
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// left image
UIImageView *image = [[UIImageView alloc] init];
[image setFrame:CGRectMake(7, 7, 30, 30)];
[image.layer setCornerRadius:image.frame.size.width/2];
[image setClipsToBounds:YES];
[image.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[image.layer setBorderWidth:0.3f];
[cell.contentView addSubview:image];
//favorites image button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(0, 0, 25, 25)];
[button setBackgroundColor:[UIColor clearColor]];
[button setImage:[UIImage imageNamed:#"unfavorites.png"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"favorites.png"] forState:UIControlStateSelected];
[button setTag:100]; //tag needed later
[button addTarget:self action:#selector(addToFavs:event:) forControlEvents:UIControlEventTouchUpInside];
[button setShowsTouchWhenHighlighted:YES];
[cell setAccessoryView:button];
switch(indexPath.section) {
case 0: { //is first section (favourite)
image.image = [UIImage imageNamed: self.iconsFavs[indexPath.row]];
cell.textLabel.text = self.favs[indexPath.row];
cell.detailTextLabel.text = self.subtitlesFavs[indexPath.row];
[button setSelected:YES];
}
break;
case 1: { //is second section (all clubs)
image.image = [UIImage imageNamed: self.icons[indexPath.row]];
cell.textLabel.text = self.objects[indexPath.row];
cell.detailTextLabel.text = self.subtitles[indexPath.row];
//change state of button (thereby change button image)
if([self.favs containsObject: self.objects[indexPath.row]]) {
[button setSelected:YES];
} else {
[button setSelected:NO];
}
}
break;
}
//separator -- do the following on viewDidLoad instead
//[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 45, 0, 0)];
return cell;
}
this be the -addToFavs:event: method --
//No need for `-accessoryButtonTappedForRowWithIndexPath:` method
//it can be done in your following `-addToFavs:event:` method alone:
-(void)addToFavs:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:currentTouchPosition];
switch(indexPath.section) {
case 0: { //is first section (favourite)
//remove from favourites
//get indexPath for appropraite row in second section
NSUInteger i_indexOfFavInMain = [self.objects indexOfObject:self.favs [indexPath.row]];
NSIndexPath *indexOfFavInMain = [NSIndexPath indexPathForItem:i_indexOfFavInMain inSection:1];
[self.favs removeObjectAtIndex:indexPath.row];
[self.subtitlesFavs removeObjectAtIndex:indexPath.row];
[self.iconsFavs removeObjectAtIndex:indexPath.row];
//handle second section button (for the appropriate row)
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexOfFavInMain];
UIButton *btnTemp = (UIButton *)[cell viewWithTag:100];
[btnTemp setSelected:NO];
//reload first section
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
}
break;
case 1: { //is second section (all clubs)
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIButton *btnTemp = (UIButton *)[cell viewWithTag:100];
if([self.favs containsObject:self.objects[indexPath.row]]) {
//remove from favourites
[self.favs removeObject:self.objects[indexPath.row]];
[self.subtitlesFavs removeObject:self.subtitles[indexPath.row]];
[self.iconsFavs removeObject:self.icons[indexPath.row]];
[btnTemp setSelected:NO];
} else {
//add to favourites
[self.favs addObject: self.objects[indexPath.row]];
[self.subtitlesFavs addObject: self.subtitles[indexPath.row]];
[self.iconsFavs addObject: self.icons[indexPath.row]];
[btnTemp setSelected:YES];
}
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
}
break;
}
}
Here's the solution. Moving everything to accessoryButoonTappedForRowWithIndexPath and having four different cases did the trick. Also make sure to not have strings that are the same in the arrays otherwise it will remove all of them and you will get an index error.
-(void)addToFavs:(id)sender event:(id)event {
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
if(indexPath!=nil){
[self tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath];
}
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
if ([self.favs count]==0) {
NSLog(#"adding first favorite %#",[self.objects objectAtIndex:indexPath.row]);
[self.favs addObject:[self.objects objectAtIndex:indexPath.row]];
[self.subtitlesFavs addObject:[self.subtitles objectAtIndex:indexPath.row]];
[self.iconsFavs addObject:[self.icons objectAtIndex:indexPath.row]];
}else if (indexPath.section==0){
NSLog(#"removing favorite %#",[self.favs objectAtIndex:indexPath.row]);
[self.favs removeObjectAtIndex:indexPath.row];
[self.subtitlesFavs removeObjectAtIndex:indexPath.row];
[self.iconsFavs removeObjectAtIndex:indexPath.row];
}else if(indexPath.section==1 && [self.favs containsObject:[self.objects objectAtIndex:indexPath.row]]){
NSLog(#"removing favorite %#",[self.objects objectAtIndex:indexPath.row]);
[self.favs removeObject:[self.objects objectAtIndex:indexPath.row]];
[self.subtitlesFavs removeObject:[self.subtitles objectAtIndex:indexPath.row]];
[self.iconsFavs removeObject:[self.icons objectAtIndex:indexPath.row]];
}else{
NSLog(#"adding favorite %#",[self.objects objectAtIndex:indexPath.row]);
[self.favs addObject:[self.objects objectAtIndex:indexPath.row]];
[self.subtitlesFavs addObject:[self.subtitles objectAtIndex:indexPath.row]];
[self.iconsFavs addObject:[self.icons objectAtIndex:indexPath.row]];
}
[tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//cell
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell){
// left image
UIImageView *image=[[UIImageView alloc] initWithFrame:CGRectMake(7, 7, 30, 30)];
[image.layer setCornerRadius:image.frame.size.width/2];
[image setClipsToBounds:YES];
[image.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[image.layer setBorderWidth:0.3f];
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.detailTextLabel.textColor=[UIColor lightGrayColor];
cell.textLabel.text=self.objects[indexPath.row];
cell.detailTextLabel.text =self.subtitles[indexPath.row];
[cell.contentView addSubview:image];
if(indexPath.section==0){
image.image=[UIImage imageNamed:[self.iconsFavs objectAtIndex:indexPath.row]];
cell.textLabel.text=self.favs[indexPath.row];
cell.detailTextLabel.text =self.subtitlesFavs[indexPath.row];
}else{
image.image=[UIImage imageNamed:[self.icons objectAtIndex:indexPath.row]];
}
//separetor
[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 45, 0, 0)];
//favorites image button
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
CGRect frame = CGRectMake(0.0, 0.0, 25, 25);
button.frame = frame;
button.showsTouchWhenHighlighted = YES;
[button setImage:[UIImage imageNamed:#"unfavorites.png"] forState:UIControlStateNormal];
[button setImage:[UIImage imageNamed:#"favorites.png"] forState:UIControlStateSelected];
[button addTarget:self action:#selector(addToFavs:event:) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
cell.accessoryView = button;
}
return cell;
}