cell subview duplicating issue in UITableView - ios

I have a custom cell with a badge which display some information.I want to set the badge image and text for some cells only(depends on some flag that i get from web service response). But when i reuse the cell, the badge and its text is getting duplicated. How can it be resolved.
The Badge and its text are a part of the custom cell and not added as subview via code.
- (void) setBadgeText:(VBMerchantDealCell *)cell withObject:(VBDeals *)deals{
if ([deals.dealType intValue] == PUNCHCARDDEAL) {
if ([deals.punchStatus intValue] == UNIV_INDEX_ONE && ![VBUtility isNullValue:deals.punchSpecialMessage]) {
[cell.lblBadgeLabel setText:deals.punchSpecialMessage];
}else {
[cell.lblBadgeLabel setText:[self getBadgeTextForPCD:deals]];
}
return;
}
}

Try the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Cell configurations
[self setBadgeText:indexPath :deals];
return cell;
}
- (void) setBadgeText:(NSIndexPath *)indexPath withObject:(VBDeals *)deals
{
[self.tableView beginUpdates];
YourTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"cellIdentifier" forIndexPath:indexPath];]
if ([deals.dealType intValue] == PUNCHCARDDEAL)
{
if ([deals.punchStatus intValue] == UNIV_INDEX_ONE && ![VBUtility isNullValue:deals.punchSpecialMessage])
[cell.lblBadgeLabel setText:deals.punchSpecialMessage];
else
[cell.lblBadgeLabel setText:[self getBadgeTextForPCD:deals]];
}
[self.tableView endUpdates];
}

Related

Expanding a table cell on clicking a button outside it in objective c

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates]; // tell the table you're about to start making changes
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
self.expandedIndexPath = nil;
} else {
self.expandedIndexPath = indexPath;
}
[tableView endUpdates]; // tell the table you're done making your changes
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
return 200.0; // Expanded height
}
return 44.0; // Normal height
}
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index
{
This is a function of getting the index , when clicking a pie chart.
what i need to do is expand the corresponding row of table when pie is selected
}
#end
If i got your idea you need to select the row at index path
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index
{
// get indexPath with index
// remember if you have few sections then you will need to update inSection:0 value
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
[yourTableView selectRowAtIndexPath:indexPath
animated:NO
scrollPosition:UITableViewScrollPositionNone];
// This will also Highlighted the row. Then delegate
[yourTableView.delegate someTableView didSelectRowAtIndexPath:indexPath];
}

ios 9 UITableView freezes when deleting cell and does not show confirmation title

I have a code written in Objective-C for deleting cells from tableview.
Here's the code:
- (BOOL)tableView:(UITableView *)tableView
canEditRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == (self.numberOfAddsShowing - 1) && (*moreAvailable)) {
return NO;
}
if (isEditable) {
return YES;
}
return NO;
}
- (NSString *)tableView:(UITableView *)tableView
titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
return #"حذف";
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
// If row is deleted, remove it from the list.
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSInteger rowNumber = indexPath.row;
if (rowNumber >= self.addsToShow.count) {
return;
}
HJAdd *adToDelete = [self.addsToShow objectAtIndex:rowNumber];
if (!self.adsToDelete) {
self.adsToDelete = [NSMutableArray array];
}
[self.adsToDelete
addObject:[[NSNumber numberWithInteger:adToDelete.addId] stringValue]];
[self.addsToShow removeObjectAtIndex:rowNumber];
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:#[ indexPath ]
withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
[self setEditButtonState];
}
The problem is that when I enter edit mode and try deleting the cell, the confirmation title is not shown and I am unable to delete the cell. When I finish editing mode, the UITableView is no longer scrollable. Swipe to delete is also not working. When I swipe, the tableView enters edit mode but I cannot see the delete button.
When I run the app in Simulator with iOS 8.1 or lower, its working fine.
Here's a video I uploaded to Youtube to show the problem.
Any help would be appreciated. Thanks to all!
You don't need [tableView beginUpdates]; and [tableView endUpdates];.
I think these are for code outside of the commitEditingStyle method.
In the TableView Programming Guide these are not used.
if you have a button bar Item
ViewDidload
self.navigationItem.rightBarButtonItem = self.editButtonItem;
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
TableAccountViewCell *accountCell = [tableView cellForRowAtIndexPath:indexPath];
if ([accountCell.myLabel.text isEqualToString:ADD_USER])
{
return NO;
}
// Return YES if you want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[menuItems removeObjectAtIndex:indexPath.row];
[_myTableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
//
// Start SQL Delele Account.
//
}
}

iPhone - UILabel staying outside of the UITableViewCell

I am making a UITableViewController that resizes UITableViewCell when I select the cell.
My problem is that the content that should be hidden when the cell is not expanded (UILabel), is always visible.
What am I doing wrong? Here is my code:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"TableViewCell";
TableViewCell *cell = (TableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:#"TableViewCell" owner:self options:nil] objectAtIndex:0];
}
cell.label.text = #"cenas";
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.selectedCellIndexPath != nil && indexPath.row == self.selectedCellIndexPath.row) {
return 200;
}else{
return 44;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.selectedCellIndexPath != nil && self.selectedCellIndexPath.row == indexPath.row) {
self.selectedCellIndexPath = nil;
}else{
self.selectedCellIndexPath = indexPath;
}
[tableView beginUpdates];
[tableView endUpdates];
}
And here are some pictures of what is happening:
In cellForRowAtIndexPath put the following code
if (self.selectedCellIndexPath != nil && indexPath.row == self.selectedCellIndexPath.row)
{
[YourLabel setHidden:NO];
}
else
{
[YourLabel setHidden:YES];
}
I found! I finally found!
I inserted inside of cellForRowAtIndexPath: the following:
[cell setClipsToBounds:YES];
This makes the content be only inside the cell
You need to manually hide/show the labels (Preferably with animation). Just because they are not inside the cells height, it doesn't mean they are hidden.
-(void)setSelectedCellIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell *oldCell = [self.tableView cellForRowAtIndexPath:_selectedIndexPath];
//oldCell can be nil due to possibility that it's not on screen.
[self hideOutletsForCell:oldCell];
_selectedIndexPath = indexPath;
UITableViewCell *newCell = [self.tableView cellForRowAtIndexPath:_selectedIndexPath];
[self showOutletsForCell:newCell];
}
Also, you need to reset the outlets in cellForRowAtIndexPath, and only show outlets for the indexPath that is your _selectedIndexPath

Selecting UITableViewCell in editing mode doesn't show rounded checkmark on the left

I have a UITableViewController that toggles into its editing mode when the user presses a button in the toolbar. I want the user to select multiple cells and then put a rounded red checkmark on the left side of each selected cell. I've selected Multiple Selection During Editing in the table view in Storyboard and no accessory / editing accessory for my custom cell.
The problem is that I can find each tapped cell in the tableView's indexPathsForSelectedRows, but the red checkmark on the left of each selected cell doesn't appear. However, after leaving editing mode, each selected cell shows a checkmark accessory on the right (which I don't need anymore after finishing editing).
While editing:
After editing:
Here is what I did in code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.editing)
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone)
{
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
}
}
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if (tableView.editing)
{
cell.accessoryType = UITableViewCellAccessoryNone;
for (NSIndexPath *selectedIndex in [self.tableView indexPathsForSelectedRows])
{
if ([selectedIndex isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
}
}
...
Thanks!
If anyone comes across the same issue, here is a snipped of how I've solved it. I have a toolbar button connected to an IBAction that toggles the UITableView's editing mode. When editing is enabled, the user can select rows and hit a delete button which has the number of selected rows set in its label.
#interface TableViewController ()
{
NSMutableArray *selectedCellRows; // Used to remember which cells have been selected during editing mode
}
- (IBAction)toggleEditing:(id)sender;
#end
#implementation TableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GeneralReservationCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CELL_IDENTIFIER];
// Set up the cell...
[self configureCell:cell forTableView:tableView atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(GeneralReservationCell *)cell forTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{
// Basic layout
cell.nameLabel.text = #"Some text";
cell.selected = NO;
if (tableView.editing)
{
for (NSIndexPath *selectedIndex in selectedCellRows)
{
if ([selectedIndex isEqual:indexPath])
{
cell.selected = YES;
break;
}
}
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.editing)
{
[selectedCellRows addObject:indexPath];
[self updateEditingToolbarButton];
}
else
{
// Do whatever you do normally when the cell gets selected
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.editing)
{
[selectedCellRows removeObject:indexPath];
[self updateEditingToolbarButton];
}
}
- (void)updateEditingToolbarButton
{
int selectedRows = [self.tableView.indexPathsForSelectedRows count];
if (selectedRows == 0)
{
[deleteBarButton setTitle:#"delete"];
deleteBarButton.enabled = NO;
}
else
{
[deleteBarButton setTitle:[NSString stringWithFormat:#"delete (%d)", selectedRows]];
deleteBarButton.enabled = YES;
}
}
#pragma mark - IBActions
- (IBAction)toggleEditing:(id)sender
{
if(self.tableView.editing)
{
[self.tableView setEditing:NO animated:YES];
[selectedCellRows removeAllObjects];
[self showToolbarInEditingMode:NO];
}
else
{
[self.tableView setEditing:YES animated:YES];
[self showToolbarInEditingMode:YES];
}
}
#end
Additionally, I set the Editing Accessory to none in Interface Builder.
If you want the rounded circle to be filled when the cell is checked, you need to set the cell's selectionStyle to other than none.
cell.selectionStyle = .blue
This can also be set in the interface builder.
Also you if you don't want the checkmark when not editing the tableView, you need to set the cell's accessoryType to .none in your else block.
if tableView.isEditing {
...
} else {
cell.accessoryType = .none
}

How to toggle UITableView Cell selected status

I have a UITableView with a custom Cell, the cell contains a UIImageView and a UILabel. Now When I load my table first time, It loads with a same image on each cell and different labels, which it takes from the LabelArray.
Now the image I am talking about is a radioButton, So when the user clicks the cell, the image changes. If user clicks again it changes to default state.
For this to happen, I have used this function and also I have declared a bool variable in my customcell class called selectionStatus.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell = (CustomCell* )[tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
if(cell.selectionStatus == TRUE)
{
//Do your stuff
cell.selectionStatus = FALSE;
}
else
{
//Do your stuff
cell.selectionStatus = TRUE;
}
}
if(indexPath.row == 1)
{
if(cell.selectionStatus == TRUE)
{
//Do your stuff
cell.selectionStatus = FALSE;
}
else
{
//Do your stuff
cell.selectionStatus = TRUE;
}
}
}
This works fine, (but I want to know whether it is a proper way, or can we check the cell.selected property) and I am able to get that effect. But now when I close the View and open it again the function
Edit based on below comments with #Anil
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.checkedIndexpath count] == 0)
{
[tableCell.selectionImage setImage:#"xyz.png"];
}
else
{
for (int i =0; i <[self.checkedIndexPath count]; i++)
{
NSIndexPath *path = [self.checkedIndexPath objectAtIndex:i];
if ([path isEqual:indexPath])
{
[tableCell.selectionImage setImage:#"abc.png"]
}
else
{
[tableCell.selectionImage setImage:#"xyz.png"]
}
}
return tableCell;
Regards
Ranjit
Another option for toggling UItableViewCells...
In the willSelectRowAtIndexPath return nil for NSIndexPath if cell is already selected, also set your _selectedIndexPath instance variable.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView.delegate tableView:self.tableView didDeselectRowAtIndexPath:indexPath];
indexPath = nil;
}
_selectedIndexPath = indexPath;
return indexPath;
}
In didSelectRowAtIndexPath and didDeselectRowAtIndexPath update your cell based on the property cell.selected ...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
// do stuff
} else {
// do stuff
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell.selected) {
// do stuff
} else {
// do stuff
};
}
and finally in viewDidLoad set the clearsSelectionOnViewWillAppear property...
- (void)viewDidLoad {
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
}
you have to save the index path of the selected row in didSelectRowAtIndexPath and check the index path in cellForRowAtIndexPath: set the corresponding image
Do you want multiple selection? try this...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell = (CustomCell* )[tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row == 0)
{
if(cell.selectionStatus == YES)
{
[self.checkedIndexPaths addObject:indexPath];
//Do your stuff
cell.selectionStatus = NO;
}
else
{
[self.checkedIndexPaths removeObject:indexPath];
//Do your stuff
cell.selectionStatus = YES;
}
}
}
Edit
In cellForIndexPath check like this
// Set the default image for the cell. imageXYZ
for (NSIndexPath *path in self.checkedIndexPath)
{
if ([path isEqual:indexPath])
{
//set the changed image for the cell. imageABC
}
// no need of else part
}
Do the exact we will see
Take a boolean in your model class and update it on didSelectRow method and reload table. In cellForRowAtIndexPath check this like that.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
After making your cell check like that
ModelClass *yourModel=[self.yourArray objectAtIndex:indexPath.row];
if(yourModel.selection)
[cell.customImage setImage:[UIImage imageName:#"selected"];
else
[cell.customImage setImage:[UIImage imageName:#"un_selected"];
}
Check this link
https://github.com/adnanAhmad786/Quiz-View--TableView
First of all for toggling purpose declare a bool value selectionStatus in tableview cell class like this:
#property(nonatomic)BOOL selectionStatus;
Declare a NSMutableArray to store the selected indexpaths (for multi-selection purpose)
self.checkedIndexPaths = [[NSMutableArray alloc] init];
In didSelectRowAtIndexPath
a. if Bool value selectionStatus is No Insert indexPath to NSMutableArray checkedIndexPaths and set cell.selectionStatus = YES
b. if Bool value selectionStatus is Yes Remove indexPath from NSMutableArray checkedIndexPaths and set cell.selectionStatus = NO
c. Reload tableView each time
Find the code below :
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
tableCell = [self.tableView cellForRowAtIndexPath:indexPath];
if(cell.selectionStatus == YES)
{
[self.checkedIndexPaths removeObject: indexPath];
cell.selectionStatus = NO;
}
else
{
[self.checkedIndexPaths addObject: indexPath];
cell.selectionStatus = YES;
}
[self.tablee reloadData];
}
In cellForRowAtIndexPath
a. First set cell image to unchecked i.e xyz.png here
[tableCell.selectionImage setImage:[UIImage imageNamed:#"xyz.png"]];
b. Set image as checked for all index paths in NSMutable array self.checkedIndexPaths
for (NSIndexPath *path in self.checkedIndexPaths)
{
if ([path isEqual:indexPath])
{
[tableCell.selectionImage setImage:[UIImage imageNamed:#"abc.png"]];
}
}

Resources