Duplicate UItableViewCell, Rows of UITableView - iphone

Here tableview after scrolling 2 3 times full up and down add images to all cells. Here is the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:#"HomeCell"];
if (cell == nil) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"HomeCell"] ;
}
VenueDC *venueObj = [subSubCategoriesArray objectAtIndex:indexPath.row];
cell.lblName.text = venueObj.name;
if ([venueObj.imagesArray count] > 0) {
[cell.ivVenue setImage:venueObj.ivVenue];
[cell.ivVenue setHidden:NO];
cell.lblName.frame = CGRectMake(80, cell.lblName.frame.origin.y, 200, cell.lblName.frame.size.height);
}
venueObj = nil;
return cell;
}
Any idea what's happening here?
Image is only in one object, on first load it shows one cell with image, but after scrolling it starts showing images on other cell too.

Solved it like this, first i set the lblName frame to its original position, so it reset its position everytime the cell is used
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:#"HomeCell"];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HomeCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (HomeCell *) currentObject;
break;
}
}
}
VenueDC *venueObj = nil;
venueObj = [subSubCategoriesArray objectAtIndex:indexPath.row];
cell.lblName.text = venueObj.name;
[cell.ivVenue setHidden:YES];
cell.lblName.frame = CGRectMake(20 , 19, 250, 20);
if (venueObj.ivVenue) {
[cell.ivVenue setImage:venueObj.ivVenue];
[cell.ivVenue setHidden:NO];
cell.lblName.frame = CGRectMake(80, cell.lblName.frame.origin.y, 200, cell.lblName.frame.size.height);
}
return cell;
}

UITableViewCells get reused, which is what the dequeueReusableCellWithIdentifier: method does. To save memory the UITableView only instantiates as many cells as it is possible to see at any given point, and then just keeps on reusing them. Because of this you should always clean up your cells before reuse, that is reset all its content to nil.
If you are using a custom table view like in your case HomeCell then override -(void)prepareForReuse and set up the image to nil there.

It is happening because your cell is reuse so write this code:
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"HomeCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (HomeCell *) currentObject;
break;
}
}
}

You Need to add only one line in cellForRowAtIndexPath
NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d",indexPath.section,indexPath.row];
And change
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeCell *cell = (HomeCell *) [tableView dequeueReusableCellWithIdentifier:#"HomeCell"];
if (cell == nil) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"HomeCell"] ;
}
VenueDC *venueObj = [subSubCategoriesArray objectAtIndex:indexPath.row];
cell.lblName.text = venueObj.name;
[cell.ivVenue setImage:nil];
if ([venueObj.imagesArray count] > 0) {
[cell.ivVenue setImage:venueObj.ivVenue];
[cell.ivVenue setHidden:NO];
cell.lblName.frame = CGRectMake(80, cell.lblName.frame.origin.y, 200, cell.lblName.frame.size.height);
}
venueObj = nil;
return cell;
}

You need an else statement:
else {
venueObj = nil;
}

Related

Custom Cell UITableview

I want to have a custom cell in my UITableview. I have tried it with the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray* views = [[NSBundle mainBundle] loadNibNamed:#"Cell" owner:nil options:nil];
for (UIView *view in views) {
if([view isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell*)view;
}
}
}
[cell setLabelText:[daten objectAtIndex:indexPath.row]];
return cell;
}
But I am getting an exception on that line:
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
I'm almost sure that you have lost connection in your XIB file. If commentLabel is still exists you should either delete it and create a new outlet or check the outlets section and delete extra connection and all will be alright!!
EDIT:
This error occurs when you have two outlets connected to the same label in IB.
This is how I made my custom cell and called it from the class :-
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:[cell reuseIdentifier]];
if (cell == nil)
{
[[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
cell = customCell;
customCell = nil;
}
// Configure the cell.
cell.serialLabel.text = [[NSNumber numberWithInt:indexPath.row+1]stringValue];
cell.textLabel.textColor=[UIColor whiteColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
if u are not using the latest ios SDK, make sure that u have written
#synthesize commentLabel;
in CustomCell
Try cleaning the build folder, or try Simulator -> Reset Content and Settings.

Why does Custom UITableViewCell causes an NSInvalidArgumentException?

i have created a custom UITableViewCell, but when I dequeue the cell, sometimes it throws an NSInvalidArgumentException:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell lblMonth]: unrecognized selector sent to instance 0x6aa7df0
Now, my custom UITableViewCell does have an attribute lblMonth, so I am confused why it is throwing this error. Below is the code I use to dequeue the cell:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell;
cell = [(CustomCell*)[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
if (cell == nil){
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"New_Phone" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[CustomCell class]])
{
cell = (CustomCell *)currentObject;
break;
}
}
}
CGFloat emival= emi;
CGFloat curinterest = balarray[indexPath.row] * interset;
if(indexPath.row == tenure){
emival = balarray[indexPath.row-1] + curinterest;
}
CGFloat curamnt = emival - curinterest;
balarray[indexPath.row]=balarray[indexPath.row]-curamnt;
[[cell lblMonth]setText:[NSString stringWithFormat:#"%d", indexPath.row+1]];
[[cell lblEMI]setText:[NSString stringWithFormat:#"%.f", emival]];
[[cell lblInterest]setText:[NSString stringWithFormat:#"%.f", curinterest]];
[[cell lblPrinicipal]setText:[NSString stringWithFormat:#"%.f", curamnt]];
[[cell lblBalance]setText:[NSString stringWithFormat:#"%.f", balarray[indexPath.row]]];
return cell;
}
Please help me over this...Thanks in Advance
The problem lies in following line of code:
cell = [(CustomCell*)[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
you should use
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Because when you check for nil it will never be nil(it will not go in if case) and a UITableViewCell object is created not the custom cell object. But thats not what you want. You want to load cell from nib and dequeue it for reuse.
See Your Code you need to change FewLines with Given Lines and rest stays same.
This is Because you are making some Mistakes just Compare your code with below Code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
//below Line get cells if they Cells Exist.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//below Line Checking precrated Cells Exist
if (cell == nil) {
cell = [(CustomCell*)[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

First row in a UITableview, different from other rows

My UITableView nedd to have, in the first row, an image.
What's the problem? that when the user scrolls down the tableview and, after, he scrolls up, over the image there are the informations of the other rows!
Do you know why?
This is my code (i'm using a UITableViewCell)
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row != 0) {
return 73.0;
}
else {
return 109.0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
if (indexPath.row == 0) {
[[NSBundle mainBundle] loadNibNamed:#"customcell_3" owner:self options:NULL];
cell = cellaNib_with_image;
}
else {
[[NSBundle mainBundle] loadNibNamed:#"customcell_2" owner:self options:NULL];
cell = cellaNib;
}
}
if (indexPath.row == 0) {
UIImage *rowBackground;
UIImage *selectionBackground;
rowBackground = [UIImage imageNamed:#"image.png"];
selectionBackground = [UIImage imageNamed:#"image.png"];
cell.backgroundView = [[[UIImageView alloc] init] autorelease];
((UIImageView *)cell.backgroundView).image = rowBackground;
cell.selectedBackgroundView = [[[UIImageView alloc] init] autorelease];
((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
}
else {
NSString *elemento = [NSString stringWithFormat:#"%#", [array objectAtIndex:indexPath.row]];
UILabel *testoLabel = (UILabel*)[cell viewWithTag:1];
testoLabel.text = elemento;
//ecc... here a take the other datas
}
return cell;
}
Thanks!
When cells are scrolled, they are reused.
So, first cell may be reused for other cells, and vice versa.
I would use two CellIdentifiers, one for first row, and second for rest of the rows.
If indexPath.row == 0, create/dequeue a cell using CellID1, and configure that and return.
If indexPath.row >1, create/dequeue using CellID2, configure this and return.
If you want to keep using single cellID, then before configuring them, nil/reset all the content first so that previous data are removed.

Custom UITableViewCell only drawing one cell

I want to display custom cells, but my code is only displaying one custom table cell at once.. what am I doing wrong?
I have a UIViewController nib set up with my UITableView inside the UIView. Also there is a UITableViewCell in the nib, whose class is CustomCell (a subclass of UITableViewCell). Both the UITableView and the Cell are #sythesized IBOutlet #properties.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"CellIdentifier";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // CustomCell is the class for standardCell
if (cell == nil)
{
cell = standardCell; // standardCell is declared in the header and linked with IB
}
return cell;
}
You can use below sample code;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"CellIdentifier";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // CustomCell is the class for standardCell
if (cell == nil)
{
NSArray *objectList = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:self options:nil];
for (id currentObject in objectList) {
if([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (CustomCell*)currentObject;
break;
}
}
}
return cell;
}
You should create a new cell every time dequeueReusableCellWithIdentifier return nil
Usually it should looks like
...
if (cell == nil)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"MyCell" owner:nil options:nil] objectAtIndex:0]
}
...
p.s. instead of objectAtIbndex: you can traverse through the array returned and use isKingOfClass:[MyCell class] to find the cell
The cell must have its content set for the given index path, even if the cell itself is dequeued, e.g.:
if (cell == nil) {
/* instantiate cell or load nib */
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
}
/* configure cell for a given index path parameter */
if (indexPath.row == 123)
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
else
cell.accessoryType = nil;
/* etc. */
return cell;
If the cell == nil then you need to instantiate a new UITableViewCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"CellIdentifier";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
// Instantiate a new cell here instead of using the "standard cell"
CustomCell *cell= [[[CustomCell alloc] init reuseIdentifier:CellIdentifier] autorelease];
// Do other customization here
}
return cell;
}

Add custom action:#selector to UISwitch on TableViewCell

I have TableCellViewController for managing cells in my UITableView. Each cell has a label na UISwitch (dictTypeSwitch). A want to assign method to switch events so I can save the state of button.
So far I've done this:
assign setState function to object:
[cell.dictTypeSwitch addTarget:self action:#selector(setState:) forControlEvents:UIControlEventTouchUpInside];
function for handling event:
- (void)setState:(id)sender {
BOOL state = [sender isOn];
NSString *rez = state == YES ? #"YES" : #"NO";
NSLog(rez);
}
From sender I get UISwitch object from which I can get state.
So far everything is ok.
But if I want to save the state of UISwitch, I have to get rowIndex for this cell.
How can I achieve this?
The cells are made inside function cellForRowAtIndexPath. Se the code bellow:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"DictionariesTableCellViewController";
DictionariesTableCellViewController *cell = (DictionariesTableCellViewController *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"DictionariesTableCellViewController" owner:nil options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (DictionariesTableCellViewController *) currentObject;
break;
}
}
}
// Configure the cell...
cell.dictTypeLabel.text = [NSString stringWithFormat:#"row - %i",indexPath.row];
[cell.dictTypeSwitch addTarget:self action:#selector(setState:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
Thanks
You can use the UISwitch's .tag property to store an arbitrary integer. This can be set to the row index.
If it is possible to find the UITableViewCell from UISwitch's parent, you could get the index path with
NSIndexPath* indexPath = [theTableView indexPathForCell:theCell];