Duplication of Table View Elements - ios

Hi I realize that this question has been asked before. I tried the previous solutions however to no avail unfortunately. What I am trying to do is to get my UISwitch to appear and not duplicate itself when scrolling on the table view. This is my current attempt however the UISwitch is not being displayed at all. Any help as to what I am doing wrong would be greatly appreciated!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"RestaurantCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
Restaurant *restaurant = [restaurants objectAtIndex:indexPath.row];
UISwitch *notificationSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(245, 15, 79, 27)];
[notificationSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:notificationSwitch];
cell.textLabel.text = restaurant.name;
cell.detailTextLabel.text = restaurant.hours;
return cell;
}

What I am trying to do is to get my UISwitch to appear and not duplicate itself when scrolling on the table view
It seems you want one UISwitch to appear in all of the cells.
To address this issue, instead of creating the object in the -cellForRowAtIndexPath, you should move this code into -viewDidLoad and simply put this object on the resusable cells later.
Basically...
This should be in your -viewDidLoad:
//IMPORTANT: declare "UISwitch *notificationSwitch;" in the .h of this class
notificationSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(245, 15, 79, 27)];
[notificationSwitch addTarget:self
action:#selector(switchChanged:)
forControlEvents:UIControlEventValueChanged];
and only this should be left in your -cellForRowAtIndexPath
[cell.contentView addSubview:notificationSwitch];
thus we create the object just once and add the same object to the cell multiple times instead of creating multiple objects in the -cellForRowAtIndexPath (that only look the same but are infact different objects)
PS: I have assumed that your delegate and datasource are hooked up properly, i.e. the execution flow does reach-cellForRowAtIndexPath

Try to use this code instead of my static text you will put your text.It is working for me!
You can see the structure of cell Attached Image
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"CellIdentifer";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
UISwitch *notificationSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(150, 5, 79, 27)];
[notificationSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:notificationSwitch];
cell.textLabel.text = [NSString stringWithFormat:#"text label %d",indexPath.row];
cell.detailTextLabel.text =[NSString stringWithFormat:#"detail label %d",indexPath.row] ;
return cell;
}

Related

UITableView with UISwitch

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.

Eliminate Duplication of Table View Elements Upon Scroll

Hi I realize that this question has been asked before. I tried the previous solutions however to no avail unfortunately. What I am trying to do is to get my UISwitch to appear and not duplicate itself when scrolling on the table view. This is my current attempt however the UISwitch is not being displayed at all. Any help as to what I am doing wrong would be greatly appreciated!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"RestaurantCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
Restaurant *restaurant = [restaurants objectAtIndex:indexPath.row];
UISwitch *notificationSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(245, 15, 79, 27)];
[notificationSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:notificationSwitch];
cell.textLabel.text = restaurant.name;
cell.detailTextLabel.text = restaurant.hours;
return cell;
}
Try this:
UISwitch init Method what say
- (id)initWithFrame:(CGRect)frame
Parameters
frame
A rectangle defining the frame of the UISwitch object. The size components of this rectangle are ignored.
Discussion
UISwitch overrides initWithFrame: and enforces a size appropriate for the control
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"RestaurantCell";
UISwitch *notificationSwitch = nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
notificationSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[notificationSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
notificationSwitch.tag = 101;
cell.accessoryView = switchView;
}
if(!notificationSwitch) {
notificationSwitch = (UISwitch*)[cell.accessoryView viewWithTag:101];
}
Restaurant *restaurant = [restaurants objectAtIndex:indexPath.row];
switch (indexPath.section) {
case 0:
cell.textLabel.text = restaurant.name;
cell.detailTextLabel.text = restaurant.hours;
break;
default:
cell.textLabel.text = #"oh no!";
}
return cell;
}

How can I stop my table view cells loading their subviews multiple of times in iOS?

I am using FontLabel in the view cells of the table.
- (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];
}
FontLabel *author_name = [[FontLabel alloc] initWithFrame:CGRectMake(58, 10, 217, 16) fontName:#"MyriadPro-Bold" pointSize:12.0f];
author_name.numberOfLines = 1;
author_name.text = [dummyArray objectAtIndex:indexPath.row];
author_name.textColor = [UIColor colorWithRed:0.580 green:0.776 blue:0.329 alpha:1.000];
author_name.backgroundColor = [UIColor clearColor];
[cell addSubview:author_name];
return cell;
}
But the label is loaded multiple times. I can see that it is getting bolder and bolder. How can I fix it?
When you call addSubview, it's not removing the old view. remember that cells are reused so the view you added in the last iteration is still there.
You should instead subclass UITableViewCell so that you can add a UILabel to it.
Edit:
Or you can do
author_name.tag = 10;
and then
FontLabel *author_name = (FontLabel *)[cell.contentView viewWithTag:10];
when you want to retrieve it.

Is it a UITableViewController?

I want to know if this control derives from UITableViewController?
If so, how?
Thank you.
This is how you add the UISwitch view to the table cell. (As an accessory)
- (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] autorelease];
//add a switch
UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchview;
[switchview release];
}
cell.textLabel.text = [NSString stringWithFormat:#"%d", indexPath.row];
return cell;
}
yes it is a table view Controller .. Grouped style ... first section has 7 rows
I cannot say for sure if derived or not but i suppose not... you can addView to specific row so you can customize the cell ...deriving tableCell is not mandatory
Not sure what you mean.
If you mean how they have UISwitch in a table cell then its probably a subclass of UITableViewCell that they put a UISwitch in.

How can I prevent a button from disappearing while selecting a cell of TableView?

I have a custom cell in TableView and there is a button in the cell. When I select the cell, the background turns to blue and the button disappears. Is there any way to prevent this?
The cellForRowAtIndexPath like this -
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[MyTableCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
Search *current = [self.retrievedTweets objectAtIndex:indexPath.row];
cell.textLabel.text = current.text;
cell.textLabel.font = [UIFont systemFontOfSize:15.0];
cell.textLabel.numberOfLines = 2;
cell.detailTextLabel.text = current.name;
cell.imageView.image = current.userImage;
btnUncheck =[[UIButton alloc] initWithFrame:CGRectMake(400, 35, 20, 20)];
btnUncheck.backgroundColor = [UIColor redColor];
btnUncheck.layer.cornerRadius = 10;
btnUncheck.hidden =NO;
btnUncheck.tag=indexPath.row;
//[btnUncheck addTarget:self action:#selector(didSelectRowAtIndexPath:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:btnUncheck];
return cell;
}
use custom image for selected table cell. or try with buttons images.
paste below line in your tableview Delegate Method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
///// your code ///////////
cell.selectionStyle=UITableViewCellSelectionStyleNone;
//// your code////////
}
here your blue backgound will not display..
What you can do is this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{[tableView deselectRowAtIndexPath:indexPath animated:YES];}
Hope this helps
Also, if you have already implemented this, what else do you have in this delegate method?
Instead of this line:
btnUncheck = [[UIButton alloc] initWithFrame:CGRectMake(400, 35, 20, 20)];
use:
btnUncheck = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
[btnUncheck setFrame:CGRectMake(400, 35, 20, 20)];
Create a "custom" view with background color clear and set to it.
UIView* vista=[[[UIView alloc] init] autorelease];
vista.backgroundColor=[UIColor clearColor];
cell.selectedBackgroundView=vista;
The way to fix this right, is to create a custom cell that you then add a button to in the xib editor.
So, in xib editor, add a 'UITableViewCell' item. Then add the button to that cell item in the xib editor. You'll then attach your custom cell to the table in the corresponding .m file here:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I have tried this out with just a one row table and the custom cell tied as a property from the xib to the .h file that has the table view. The highlight is there and just grays out the button (still viewable). To get this to work with more rows is more involved. You'll need to load the custom utableviewcell xib and alloc your custom cell dynamically for that to work.

Resources