Add subview to UITableViewCell: Added several times when scrolling - iphone

I have some different cells in my tableView, each with different subviews. Each time a cell dissapear and reapear, the subview is addad on top of the old view, and also is added to other cells. What is the correct way to add subviews to cells without using custom cells?
Thanks in advance
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"StatisticsCell";
StatisticsCell *cell = (StatisticsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *topLevelObject = [[NSBundle mainBundle] loadNibNamed:#"StatisticsCell" owner:nil options:nil];
for (id currentObject in topLevelObject)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (StatisticsCell *)currentObject;
break;
}
}
}
if (indexPath.section == 0 && indexPath.row == 0)
{
//Add a subview here
[cell addsubview ....
}
else if (indexPath.section == 0 && indexPath.row == 1)
{
//Add a subview here
[cell addsubview ....
}
etc....

Whenever you scroll cell for row method is called, so when your cell be visible, it will add subview to the cell. Place a check that is view added already, make an ivar that is bool, and set it true when you add view, and false when you remove. Like this:
.
.
.
if (indexPath.section == 0 && indexPath.row == 0 && isFirstViewAlreadyAdded== NO)
{
//Add a subview here
[cell addsubview ....
isFirstViewAlreadyAdded = YES;
}
else if (indexPath.section == 0 && indexPath.row == 1 && isSecondViewAlreadyAdded == NO)
{
//Add a subview here
[cell addsubview ....
isSecondViewAlreadyAdded = YES;
}
.
.
.

You can check whether that subView is already added to cell or not.
UIView *subView = [tableCell viewWithTag:tagOfYourSubView];
if (subView) {
//subView exists
}
else {
//subView does not exist
}
If it is not added then you can add.

Don't add the subview every time..
You should add the subview in the if(cell==nil) block.
And after that you can set the hidden property as true or false according to indexpath.row.
like:
if (indexpath.row == 0)
img1.hidden = FALSE;
else
img1.hidden = TRUE;

Related

Add Button to separate cell

I need to add button to separate cells
Button in yellow circle
i can add to all cells like [cell addSubview:myButt]; but it works to all cells, i need only for 5, 6, 7, 8 cells;
Do i need to write a custom UITableViewCell?
And that line(black arrows), as i understand it is Section, how can i create it with no title, with line(image) and in middle of the table? Thank's to all.
P.S. Sorry for my English
You can hide your section header like this :
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.0f;
// or 1.0 as per your line
}
For buttons on your cells, you have to create a custom cell Class and then use that in cellForRowAtIndexPath method. You can also use tags for this. You can do it like this:
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:"Cell"];
if (cell == nil) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if(indexPath.section == 1)
{
if(indexPath.row>=5 && indexPath.row <=8)
{
//adding buttons to custom cell
}
}
}
You could use the tag property of UIView to keep track of your button but I'd really recommend to use a custom UITableViewCell. With that being said, below is the code you could use. It is optimized to not add the same button over and over but just when you need it, and hide it in cases you don't need it.
static int kButtonViewTag = 3294802;
UIButton *button = [cell.contentView viewWithTag:kButtonViewTag];
BOOL shouldDisplayButton = indexpath.row == 5 || indexpath.row == 6 || indexpath.row == 7 || indexpath.row == 8;
// If the button should be displayed and is not
//
if (shouldDisplayButton) {
// Add button here
//
if (!button) {
button = // Init your button
button.tag = kButtonViewTag;
[cell.contentView addSubview:button]
}
else if (button.isHidden) {
button.hidden = NO;
}
}
// If the button should not be displayed but is
//
else if (!shouldDisplayButton && button && !button.isHidden) {
button.hidden = NO;
}
And then for your section:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
CGFloat tableWidth = tableView.frame.size.width;
CGFloat padding = 10; // Add some padding
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(padding, 0, tableWidth - padding * 2, 1)];
[view setBackgroundColor:[UIColor greyColor]; //your background color...
return view;
}
Just add button in cellforrow method :
If (indexpath.row == 3 || indexpath.row == 4 || indexpath.row == 5 || indexpath.row == 3)
{
// add button here
// tag button here
Button.tag = indexpath.row ;
}

UITextField clears while scrolling in UITableView - custom cell

I am trying to save certain values from UITextField however, I am unable to do that because whenever I scroll there is nothing in UITextField. I am using a custom cell. I understand that custom cell has to load in a specific view and for that reason I'm using textFieldDidEndEditing to store values in an array. However, I get the following error message:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Help is much appreciated!! My code is below and I'm quite new in IOS Development.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
if (indexPath.row == 7) {
static NSString *CellIdentifier = #"RevButtonCell";
RevButtonCell *cell = (RevButtonCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"RevButtonCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
[cell.revsaveB addTarget:self action:#selector(revaddparse:) forControlEvents:UIControlEventTouchUpInside];
cell.reveditdeleteB.hidden = YES;
cell.reveditsaveB.hidden = YES;
cell.revsaveB.hidden = NO;
cell.revdeleteB.hidden = NO;
}
return cell;
} else {
static NSString *CellIdentifier = #"TextCell";
TextCell *cell = (TextCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"TextCell" owner:self options:nil];
cell = [topLevelObjects objectAtIndex:0];
}
cell.detaillabel.text = [revdetailsA objectAtIndex:indexPath.row];
cell.detailtext.placeholder = #"Enter Text";
cell.detailtext.tag = indexPath.row;
cell.detailtext.delegate = self;
if (indexPath.row == 0) {
cell.detailtext.text = dateS;
}
if (indexPath.row == 1) {
cell.detailtext.text = clientS;
}
if (indexPath.row == 2) {
cell.detailtext.text = productS;
}
if (indexPath.row == 3) {
cell.detailtext.text = amountS;
}
if (indexPath.row == 4) {
cell.detailtext.text = qtyS;
}
if (indexPath.row == 5) {
cell.detailtext.text = taxS;
}
if (indexPath.row == 6) {
cell.detailtext.text = totalS;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[client insertObject:clientS atIndex:0];
[product insertObject:productS atIndex:0];
[date insertObject:dateS atIndex:0];
[amount insertObject:amountS atIndex:0];
[qty insertObject:qtyS atIndex:0];
[tax insertObject:taxS atIndex:0];
[total insertObject:totalS atIndex:0];
}
Initialize the vales of to empty string as
clientS = #"";
productS = #"";
dateS = #"";
amountS = #"";
qtyS = #"";
taxS = #"";
totalS = #"";
just use every CellIdentifier are different use CellIdentifier like bellow
and also here after use this code ,not required to create array and insert object in it so dont create array just use this code..
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d%d",indexPath.section,indexPath.row];
use this CellIndentifier insted of another like "TextCell" and "ButtonCell"
i hope this help you...
:)
It looks from your code like you are trying to implement static cells in a table view. What you might want to consider is using a storyboard and creating a table view that supports static table cells just using Interface Builder. This will allow you to eliminate the entire cellForRowAtIndexPath: method. If you can't use storyboards, then you will have to manage your cells the way you're doing it, but in my book, anytime you can eliminate code, you should.
If you're going to use a storyboard, there a couple things you should know:
Your view controller in the storyboard needs to be a table view controller
You set the table Content field to "Static Cells"
Add the textfields you want to use to each of the cells by dragging them into the cells you add
Create outlets in your view controller header and then drag connections to them in interface builder
There are some tutorials out there on using table views with static cells. They can be a little long, however, stick with them and you should be able to produce the results you're looking for.
Best regards.

EXC_BAD_ACCESS When I click a button inside a custom UITableViewCell

I build a TableView with custom TableViewCell, the first custom cell have a tool bar and some Bar button Item and also a simple button for test.
The problem is : When I click in any bar button item or into simple button I have a EXC_BAD _ACCESS ?
This is my code to build the tableview cells :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"taskCell";
if(indexPath.row != 0){
TaskCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"TaskCell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (TaskCell*)view;
}
}
}
return cell;
}
else{
if (travelInfoCell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"TravelInfo" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
travelInfoCell = (TravelInfo*)view;
}
}
}
travelInfoCell.selectionStyle = UITableViewCellSelectionStyleNone;
return travelInfoCell;
}
}
I planed to delegate the action code to the TableViewController, but for the instant I can not even hit the breakpoint in front of the button IBAction.
Code into the TravelInfo.m and is not working and throw to me EXC_BAD _ACCESS :
- (IBAction)doAccepted:(id)sender {
NSLog(#"accepted");
//[delegate travelAccepted];
}
Do have any solution ?
Here's your problem:
travelInfoCell = (TravelInfo*)view;
You are not keeping a reference to the view, so there is an implicit limited life expectancy to the view variable. You'll need to retain to keep a reference. Do this:
travelInfoCell = [(TravelInfo*)view retain];
Don't forget to release the cell and nil it out on viewDidUnload

How to use different cell in one table view?

How to use 3 different cells on one uitableview? I have 3 buttons now When i press any button then cell of table view should be changed. Please help
In the button's action method, save which button was tapped & reload the row in which you want to change the cell.
-(void)button1Tapped:(id)sender
{
self.buttonIndex = 1;
NSArray* arr = [[NSArray alloc] initWithObjects:self.indexPathOfConcernedCell, nil];
[self.tableView reloadRowsAtIndexPaths:arr withRowAnimation:UITableViewRowAnimationNone];
[arr release];
}
Then, in cellForRowAtIndexPath: return the cell one the basis of which button was pressed-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath == self.indexPathOfConcernedCell)
{
if(self.buttonIndex == 1)
{
Cell1* cell = (Cell1*) [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier1"];
if(cell == nil)
{
cell = [[[Cell1 alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"CellIdentifier1"] autorelease];
}
}
else if(self.buttonIndex == 2)
{
//do similar stuff
}
//do similar stuff for buttonIndex 3 here
}
}
else
{
//your regular stuff
}
return cell;
}

Segmented UITable's unstability

I have a table that has its content filled using one of the two datasets provided based on the value of the segmented control attached. The data is pulled from the web.
The application crashes when I move back and forth between the two datasets and then select a table cell. The application works without hiccups when I use two separate table rather than a single table with a segmented control. Somehow combining them renders the application unstable.
One of the most error is when I tapped one the Acells of A table and while its loading I tapped the segment index=1, which will load B. it cause unrecognized selector being sent. meaning of the parameter o A table to being sent to B table.
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier0;
if (choice == 0) {
CellIdentifier0 = #"ACell";
} else if (choice == 1) {
CellIdentifier0 = #"BCell";
}
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier0];
if (cell == nil) {
if (choice == 0) {
[[NSBundle mainBundle] loadNibNamed:#"ACell" owner:self options:nil];
cell = ACell;
self.ACell = nil;
} else if (choice == 1) {
[[NSBundle mainBundle] loadNibNamed:#"BCell" owner:self options:nil];
cell = BCell;
self.BCell = nil;
}
}
if (choice == 0) {
[(ACell *)cell setA:(A*)[contentArray objectAtIndex:indexPath.row]];
} else if (choice == 1) {
[(BCell *)cell setB:(B*)[contentArray objectAtIndex:indexPath.row]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( choice == 0) {
A = [contentArray objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"showA" object:A];
} else if (choice ==1) {
B = [contentArray objectAtIndex:indexPath.row];
[[NSNotificationCenter defaultCenter] postNotificationName:#"showB" object:B];
}
}
Assuming that ACell has the retained value when the nib file is loaded, doing self.ACell = nil; will release the older value and set ACell to nil. Now the older value is the one pointed to by cell. So technically it would be pointing to junk as it would've been deallocated because ACell is the only variable retaining the object. You can fix this by replacing,
cell = ACell;
with,
cell = [[ACell retain] autorelease];
As a sidenote, in the didSelectRowAtIndexPath: method you're doing } else if (choice = 1) {. Make sure you use == rather than = which will always evaluate to true along with changing the value of choice although it is unlikely in this case.
check choice spellings
if (choicee==0) {
[[NSBundle mainBundle] loadNibNamed:#"ACell" owner:self options:nil];
cell = ACell;
self.ACell = nil;}
else if (choice==1) {