I have used custom UITableViewCell. I have added a Gesture in it for swipe option, I have 20 cells in my tableView. If I swipe my first cell and scroll means my 11th cell also updated into my first cell value.
the following is my code snipet.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = (CustomCell*)
[tableView dequeueReusableCellWithIdentifier:#"CustomCellId”];
[cell setRequestCellDelegate:self];
[cell.swipeLeft addTarget:self action:#selector(swipeLeftAction:)];
cell.tag = indexPath.row;
cell.swipeLeft.delegate = self;
cell.swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
cell.indexpath = indexPath;
[cell.swipeRight addTarget:self action:#selector(swipeRightAction:)];
cell.swipeRight.delegate = self;
cell.swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
cell.tableHoldButtn.tag = indexPath.row;
return cell;
}
Please help to find the solution for this.
This is happenning because as soon as your first swiped cell goes off the screen it's being put into queue for reuse. Then when your 10th cell should come on the screen it's not being created but rather 1st cell is being reused. And since you have swiped it, it will be dequeued in exact same state as it left the screen.
You should track changes in table view controller which cell should be swiped and restore that state in your cellForIndexPath data source method.
I think its better to use tableView delegate methods instead on applying gesture. you can use
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
Additionally you can also customise the edit button appearance by:
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath;
CustomCell *cell = (CustomCell*)
[tableView dequeueReusableCellWithIdentifier:[NSString stringwithFormat:"%ld",indexPath.row]];
reuse Identifier change to the string of indexPath.row
I hope my experiment can help you
note: do not register cell in other place,remove register cell in other place (maybe in viewdidLoad )
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// CustomCell *cell = (CustomCell*)
// [tableView dequeueReusableCellWithIdentifier:#"CustomCellId”];
// need not register cell in other ,like viewdidLoad
CustomCell* cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"%#",indexPath.row]];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[NSString stringWithFormat:#"%#",indexPath.row]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[cell setRequestCellDelegate:self];
[cell.swipeLeft addTarget:self action:#selector(swipeLeftAction:)];
cell.tag = indexPath.row;
cell.swipeLeft.delegate = self;
cell.swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
cell.indexpath = indexPath;
[cell.swipeRight addTarget:self action:#selector(swipeRightAction:)];
cell.swipeRight.delegate = self;
cell.swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
cell.tableHoldButtn.tag = indexPath.row;
return cell;
}
Related
I use storyboard and Auto Layout. I add UISwitch to my cell with tag 5. When I choose first UISwitch and scroll down I see that other UISwitch is also turned on and if I scroll up my first UISwitch is turned off. How to fix this?
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UISwitch* switchView = (UISwitch *)[cell viewWithTag:5];
[switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
return cell;
}
This is because UITableView reuse UITableViewCell so one cell can be use more than once in different indexPaths, in this situation its your responsibility to maintain the state of UITableViewCell subViews. Better place to do this is cellForRowAtIndexPath where you are returning cell add logic to make show/hide UISwitch or to select accurate state i.e. on or off, you can keep that flag in dataSource object and then you can check for that flag to make set right state for UISwitch
Try This:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellSetting";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [self.settingsArray objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if ([[self.settingsArray objectAtIndex:indexPath.row] isEqualToString:ROW_PRIVATE_BROWSING])
{
self.privateBrowsingSwitch =[[UISwitch alloc]initWithFrame:CGRectMake(cell.frame.size.width-65, 10, 30, 30)];
if (ApplicationDelegate.privateBrowsing)
{
[self.privateBrowsingSwitch setOn:YES animated:YES];
}
[self.privateBrowsingSwitch addTarget:self action:#selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:self.privateBrowsingSwitch];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Every time cellForRowAtIndexPath is called you have to replace the specific data that needs to be displayed for a cell at that position. This includes things like labels, images and your UISwitch.
This occurs because UITableViews use a small number of cells that are reused.
In cellForRowAtIndexPath add something like this:
switchView.on = [self isSwitchOnForCellAtIndexPath:indexPath]
Then write whatever logic is required to determine if the switch should be on or not.
Issue: I only want to show the selected cells with checkmark. I don't want the grey highlight.
I tried:
cell.selectionStyle = UITableViewCellSelectionStyleNone
but didn't work.
Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
ProfileSelection *profile = [self.profileSelections objectAtIndex:indexPath.row];
cell.textLabel.text = [profile profileName];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.profileSelectionsTableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
[tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
ProfileSelection *profile = [self.profileSelections objectAtIndex:indexPath.row];
self.mobileProfileId = [profile.profileId stringValue];
[_continueButton setEnabled:YES];
}
How about this:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
The selectionStyle property should be enough to remove the highlight.
If you want to show the checkmark after the used has selected the row, you need to implement the tableView:didSelectRowAtIndexPath: method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView cellForRowAtIndexPath:visibleIndexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
In Swift, the easiest way is to deselect a cell without animation right after it has been selected:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
}
delete your this function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Try to use this your problem will be solved
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone
cell.textLabel.text = #"Checking Table View";
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Go to Storyboard. Select your Table View Cell. Set Selection to None. Then add below codes:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
This thread looks a bit old, but I actually came across a decent solution for this recently. In case anyone stumbles across this thread, I figure I might as well post an answer. Especially since I spent hours trying to track this down.
I can't find my original sources anymore, but here's what I found out:
The highlight is made by a background view on the UITableViewCell on the selectedBackgroundView property. If we have a subclass of the table cell, we can detect the transition to the editing state with willTransitionToState: and set the background view to one that is clear/white instead of the blue/gray styles.
Here's what I ended up doing, and it works pretty well.
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
// To remove the blue/gray highlight on the table cell when selected,
// set the selection background to a clear view.
if (state & UITableViewCellStateShowingEditControlMask) {
// If we're moving to an edit state, set the custom background view.
UIView *bgView = [[UIView alloc] init];
[bgView setTintColor:[UIColor whiteColor]];
[bgView setBackgroundColor:[UIColor clearColor]];
[self setSelectedBackgroundView:bgView];
} else {
// Otherwise, just remove it completely.
// The system should handle the rest.
[self setSelectedBackgroundView:nil];
}
}
The plus side to this over the other solutions I've seen is that this one is quite minimal. No need for tracking instance variables or anything else.
I'm trying to change states of the label in my table view cell.
I want to keep a cell selected while I push a different view controller and move back to the view controller with my tableview.
When I select another row I want to remove highlight of previously selected row's lable (deselect the previously selected row) and Highlight the current row's label.
Is - (void)deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated supposed to call - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated with highlighted 'NO' for that Cell ?
Note: I'm not UITableViewController.
Keep cell selected:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selected = YES;
//Other code
}
Ensure that the class cell don't have selected = NONE in interface builder.
Unselect last row:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSIndexPath *currentSelectedIndexPath = [tableView indexPathForSelectedRow];
if (currentSelectedIndexPath)
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.selected = NO;
}
return indexPath;
}
First, you should set TableviewCell properly [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; in method :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
Other then this, you can set custom background of selected cell by
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor colorWithWhite:0.97 alpha:1.0];
bgColorView.layer.masksToBounds = YES;
[cell setSelectedBackgroundView:bgColorView];
For Your highlight selected cell problem, you can use Simple flag like
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *ip= [NSIndexPath indexPathForRow:flagForLastSelectedRow inSection:0];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
flagForLastSelectedRow=indexPath.row;
}
I have a tableView, with custom cells.
In each cell i have a UIButton. When i click the button inside the cell i want that cell to highlight, but when i click o the cell i don't want this to happen.
Do you know any way to do this?
thank you
until now i have this code:
- (IBAction)buttonMethod: (id)sender {
UIButton *b = (UIButton *) sender;
UITableViewCell *cell = (UITableViewCell *)[[[sender superview] superview] superview];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[cell setSelected:YES animated:YES];
}
but the cell is highlighted also in -didSelectRow.
- (UITableViewCell *)tableView: (UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"CustomCell";
CustomCell *cell = (CustomCell *) [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSAssert(cell, #"cell -> nil");
NSDictionary *cellData = [_data objectAtIndex:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[cell populateCellWithData:cellData];
return cell;
}
Use this UITableViewDelegate method:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
This way, cells can't be selected when the user taps on them, but you can still select them programatically.
Also using
selectRowAtIndexPath:animated:scrollPosition:
on your UITableView , instead of setSelected:animated: on UITableViewCell might be better. Cells can be reused and the selection will probably disappear when it happens.
You have to add following line in tableView delegate method cellForRowATIndexPath.
cell.selectionStyle =- UITableViewCellSelectionStyleNone;
You have to set cell.selectionStyle = UITableViewCellSelectionStyleNone; in cellForRowAtIndexPath method of tableView.
So you can set this style in - (IBAction)buttonMethod: (id)sender. You can add this line at the end. See below:
- (IBAction)buttonMethod: (id)sender {
UIButton *b = (UIButton *) sender;
UITableViewCell *cell = (UITableViewCell *)[[[sender superview] superview] superview];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
[cell setSelected:YES animated:YES];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
Just use UITableViewDelegate like this
-(BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath{
return NO;
}
but If I were you, I would change the background color of cell in [buttonMethod:] with UITableViewCellSelectionStyleNone
Hi i have a UITableviewCell and i put the "+" symbol in end of the UITableviewcell.My requirement is if i click the "+" sign in UITableviewcell three UITextfields displayed in Next UITableviewcell.And also i want to display 3 UITextfields in first UITableviewcell by default.And "+"signs are displayed on total tableview.But i want to display "+" signs dynamically. How can i do this functionality.please help me any body.
This is my code.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
[cell.textLabel setText:#""];
UIButton *myGreenIconButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myGreenIconButton addTarget:self action:#selector(GreenIconButtonClicked:)forControlEvents:UIControlEventTouchUpInside];
[myGreenIconButton setBackgroundImage:[UIImage imageNamed:#"index.jpg"] forState:UIControlStateNormal];
myGreenIconButton.backgroundColor = [UIColor clearColor];
myGreenIconButton.frame = CGRectMake(285, 28, 25, 25);
[cell addSubview:myGreenIconButton];
return cell;
}
You should set the initial no. of sections to one and no. of rows to 3, each row has one UITextfield and then after hitting the plus button increment that no. of sections with 1 and reload the UITableview using [tableview reloaddata];.
Before that you need to add the delegate methods like - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section and - (UIView *) tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section for + button as you need it in the bottom each section.
Take a look at this question about how to add footer view to each section.
Is better use a db or a plist file to setup dynamic table, but
you can insert manually what you want inside the first table in xcode like my screen:
Then you can use this with tag:
- (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];
}
UIImageView *logoImageView = (UIImageView *)[cell viewWithTag:1];
logoImageView.image = [self.cachedImages valueForKey:identifier];
UILabel *detailLabel = (UILabel *)[cell viewWithTag:2];
detailLabel.text = (self.loadImage)[indexPath.row][#"subtitle"];
}
Set the tag on interface, select your object and go on attribute inspector:
When the table load get dynamically your image or text, to pas this information to a DetailViewController using
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
}
here you can see a UITableView plus plist tutorial:
UITableView and Plist tutorial
Hope this help you