This is my cellForRowAtIndexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(12,11,320,40)];
label.text = [animalArray objectAtIndex:indexPath.row];
[cell addSubview:label];
In the animalArray i have the following items,
Lion, Dog, Cat, Zebra, Donkey, Monkey...
The problem is;
1.) When i add the label inside the if (cell == nil) { condition i see repeated records. like Lion, Dog, Cat, Zebra and then again Lion as i scroll down.
2.) When i add it outside the if (cell == nil) { the records overlap as i scroll.
I understand that this is because the cell is reusing its self, and i am creating a Label each time (so it gets overlapped). I don't know how to fix this issue programatically. Can someone please help me.
EDIT:
I have just displayed 1 label here. but i have more than one label to display. and also some UIComponants.
I writing this code without checking syntax:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(12,11,320,40)];
label.tag = 556;
[cell.contentView addSubview:label];
}
UILabel *cellLabel = (UILabel *)[cell.contentView viewWithTag:556];
cellLabel.text = [animalArray objectAtIndex:indexPath.row];
you dont have to add label to your table cell. it already has cell.textLabel.text=#"some string".
replace this part:
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(12,11,320,40)];
label.text = [animalArray objectAtIndex:indexPath.row];
[cell addSubview:label];
with this:
cell.textLabel.text=[animalArray objectAtIndex:indexPath.row];
The best approach would be subclassing UITableViewCell and adding all labels. That way you need to set labels' text properties outside of the
if (cell == nil){...}
block.
use this by removing if(cell == nil)
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(12,11,320,40)];
label.text = [animalArray objectAtIndex:indexPath.row];
[cell addSubview:label];
[label release];
Related
Does this code triggers when I call [Self.table reloadData]
if (cell == nil){...}
Im wondering because I have added a UITextField in the cell:
//cellForRowAtIndexPath
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
recepientTextField = [[UITextField alloc] initWithFrame:CGRectMake(cell.contentView.frame.origin.x+40, 10, 469, 20)];
[cell addSubview:recepientTextField];
}
recepientTextField.text = recipient;
return cell;
Then I download some stuff from internet and I then want to show the info in recepientTextField.text in the TableView. So I call set a new value to recipient variable and then [self.tableView realoadData] But it crashes. I think it has to do with the textfields allocation. How can I fix this? How can I change the text afterwards?
When reloaded the cell != nil case comes and there the recipientTextField has null reference and hence the crash
Try this
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
recepientTextField = [[UITextField alloc] initWithFrame:CGRectMake(cell.contentView.frame.origin.x+40, 10, 469, 20)];
[recepientTextField setTag:333];
[cell addSubview:recepientTextField];
}
UITextField *TF=(UITextField *)[cell viewWithTag:333];
TF.text = recipient;
return cell;
i am new in iPhone development. I am developing an app which contains tableview with label inside the cell. I have placed different label for each row like this if(indexpath.row == 0) like this for each cell row i have done it. But when i am scrolling the tableview my label are getting mixed. Please help me!
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.row == 2)
{
pendingListNumberLabel = [[UILabel alloc] init];
pendingListNumberLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
pendingListNumberLabel.textAlignment = UITextAlignmentLeft ;
pendingListNumberLabel.textColor = [UIColor orangeColor];
pendingListNumberLabel.frame = CGRectMake(240, 6, 110, 30);
[pendingListNumberLabel setBackgroundColor:[UIColor clearColor]];
[cell addSubview:pendingListNumberLabel];
}
cell.textLabel.text = [affiliationsArray objectAtIndex:indexPath.row];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
You are adding the UILabel as a subview, that is the mistake here.
Normally you would use a custom UITableViewCell for this kind of stuff, but a quick fix is this:
if (indexPath.row == 2)
{
pendingListNumberLabel = [[UILabel alloc] init];
pendingListNumberLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
pendingListNumberLabel.textAlignment = UITextAlignmentLeft ;
pendingListNumberLabel.textColor = [UIColor orangeColor];
pendingListNumberLabel.frame = CGRectMake(240, 6, 110, 30);
[pendingListNumberLabel setBackgroundColor:[UIColor clearColor]];
pendingListNumberLabel.tag = 1337
[cell addSubview:pendingListNumberLabel];
} else {
for (UIView * subView in [cell subviews]) {
if ([subView tag] == 1337) {
[subView removeFromSuperview];
}
}
}
This is happening because you are using reusable cells and not in a right way ..
just replace your code -
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
with this -
UITableViewCell *cell = [[UITableViewCell alloc] init];
the above code can solve your issue, but this is not good if there are a large number of cells. In that case you should use reusable cells.
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
else
{
UILabel *titleLbl = (UILabel *)[cell viewWithTag:1];
[titleLbl removeFromSuperview];
}
if (indexPath.row == 2)
{
pendingListNumberLabel = [[UILabel alloc] init];
pendingListNumberLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
pendingListNumberLabel.textAlignment = UITextAlignmentLeft ;
pendingListNumberLabel.textColor = [UIColor orangeColor];
pendingListNumberLabel.tag = 1;// Write here.....................................
pendingListNumberLabel.frame = CGRectMake(240, 6, 110, 30);
[pendingListNumberLabel setBackgroundColor:[UIColor clearColor]];
[cell addSubview:pendingListNumberLabel];
}
cell.textLabel.text = [affiliationsArray objectAtIndex:indexPath.row];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
I think it will be helpful to you.
You can fix the problem of label mixing just by omitting the if (cell == nil) checking. Use the bellow code:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//if (cell == nil) // Need not this checking
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
Use the cell allocation directly as above :)
In your tableView:cellForRowAtIndexPath: method, first get the selected row like this
NSUInteger row = [indexPath row];
then use "row" to grab your data from an NSArray that corresponds to the tableView rows and assign it to your cell's textLabel's text property like this
NSString *string = [NSString stringWithFormat:#"%#",self.allItems objectAtIndex:row];
cell.textLabel.text = string;
return cell;
And of course you would have already created a UITableViewCell with a Reuse identifier like this :
static NSString *TableIdentifier = #"TableIdentifier";
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:TableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:TableIdentifier];
}
The key is using an array that corresponds exactly to your table rows. (ie - item 0 in the Array corresponds to row 0 in the tableView) then you can't go wrong.
For solve this issue you can put cell=nil; before checking cell== nil condition or create cell every time. It will work but it is not good Habit.
This also work for Text
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = nil;
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.row == 2)
{
pendingListNumberLabel = [[UILabel alloc] init];
pendingListNumberLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
pendingListNumberLabel.textAlignment = UITextAlignmentLeft ;
pendingListNumberLabel.textColor = [UIColor orangeColor];
pendingListNumberLabel.frame = CGRectMake(240, 6, 110, 30);
[pendingListNumberLabel setBackgroundColor:[UIColor clearColor]];
[cell addSubview:pendingListNumberLabel];
}
cell.textLabel.text = [affiliationsArray objectAtIndex:indexPath.row];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
I've got a tableview loaded from an array and for some reason it's re-using the cell but loading the same information lower down the table, a second time.
http://screencast.com/t/Ig8bcqSpLzp
The video above should give you an idea of what I mean.
This is my code to load the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
accessicon *current =[arryAccess objectAtIndex:indexPath.row] ;
cell.textLabel.text = current.text;
cell.imageView.image = [UIImage imageNamed: current.iconPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
mySwitch *switchView = [[mySwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
switchView.myValue = current.iconValue;
if(totalIconValue & current.iconValue) {
[switchView setOn: YES animated:NO];
} else {
[switchView setOn: NO animated:NO];
}
[switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[switchView release];
return cell;
}
Any help will be appreciated
EDIT: I've updated my code above, however on the actual device it's still selecting items it shouldn't be - no longer reusing the names but if i scroll up and down it selects them on it's own?
see the video here: http://screencast.com/t/a9N1qbws
Tom
This code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
if (cell == nil) {
...
is fundamentally wrong. It should read:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
...
And then, anything that is row-specific should be outside that if statement.
The pattern for this, generally, should be:
dequeue a reusable cell
if you didn't get one:
allocate a new cell
perform generic cell setup, i.e. setup that applies to all cells
setup the cell for the specific row, and return it.
Hope this helps.
You aren't reusing you cells. And you are filling the cells only when the init fails. Try this code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
accessicon *current =[arryAccess objectAtIndex:indexPath.row] ;
cell.textLabel.text = current.text;
cell.imageView.image = [UIImage imageNamed: current.iconPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
mySwitch *switchView = [[mySwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
switchView.myValue = current.iconValue;
if(totalIconValue & current.iconValue) {
[switchView setOn: YES animated:YES];
} else {
[switchView setOn: NO animated:YES];
}
[switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
[switchView release];
Or develop under ios5 and get rid of the alloc and init.
You are constantly creating new rows instead of reusing the old ones.
Move the line
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
inside the if block, end move everything else you have in the if block outside of it, except the lines
mySwitch *switchView = [[mySwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = switchView;
You need to create the switch only once for row, when it is initialized (that means, in the if statement). I suggest you to create it and assign it a tag, so you can access it later by its tag. Your code now is creating a new switch everytime the cell is used, this could be the reason why the switches are behaving this way.
After using Run->Run with Performance tool->Leaks on my application, it finds a leak, but I don't know if it is a glitch by the tool?
I start the application by selecting a button, which opens a tableview (no leaks).
tableview appears and if I don't touch anything (no leaks).
If I select the first cell and cursor appears blinking (3 to 4 seconds later, leak)??
I did find something weird, in my tableview, if I try selecting any other cell, besides the first one, it will not become the first responder (this might not have to do with anything)?
If anyone has come across this or can spot or direct me to where this could be happening please let me know? Thank you.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
UITextField *FirstField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 130, 25)];
FirstField.delegate = self;
FirstField.tag = indexPath.row; [cell.contentView addSubview:FirstField];
FirstField.returnKeyType = UIReturnKeyNext;
[FirstField release];
return cell;
}
The memory leak is that due to every time you call the function you are allocating a UITextField and adding it to the cell.
Cells are reused and each time the cell is accessed to determine the content a new UITextField is added to the cell and stacked onto of each other
Move the allocation of FirstField to where the cell is allocated so that it can be reused.
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UITextField *FirstField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 130, 25)];
FirstField.tag = 1
[cell.contentView addSubview:FirstField];
[FirstField release];
}
UITextField *field = (UITextField *)[cell.contentView viewWithTag:1];
field.delegate = self;
field.returnKeyType = UIReturnKeyNext;
return cell;
I also see that you are using the field.tag to store the indexPath.row value of the cell, in that cause you might have to search the view hirachy of cell.contentView to find the TextField subview.
I am getting a really strange error and I can't figure out how to fix it: When I scroll around in my UITableView it will sometimes highlight a cell blue, even when I don't fully selected.
For example:
-Cell 1-
-Cell 2-
-Cell 3-
-Cell 4-
If I put my finger down on Cell 2 and scroll to Cell 4 it will leave Cell 2 highlighted, even though didSelectRowAtIndexPath: is never fired.
Any ideas?
EDIT
Added code:
UITableViewCell *cell = nil;
static NSString *cellId = #"StyleDefault";
cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId] autorelease];
}
cell.textLabel.text = #"Cell One";
cell.textLabel.textAlignment = UITextAlignmentCenter;
[cell setAccessoryView:nil];
return cell;
FIXED IT!
My solution was two parts:
1) In cellForRowAtIndexPath: put "cell.selected = NO;", which fixes the problem of if the cell gets touched down on then goes off screen (scrolling).
UITableViewCell *cell = nil;
static NSString *cellId = #"StyleDefault";
cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId] autorelease];
}
cell.textLabel.text = #"Cell One";
cell.textLabel.textAlignment = UITextAlignmentCenter;
[cell setAccessoryView:nil];
//Here:
cell.selected = NO;
return cell;
2) Put "[tableView deselectRowAtIndexPath:indexPath animated:YES];" into didSelectRowAtIndexPath: instead of what I used to have "[[tableView cellForRowAtIndexPath:indexPath] setSelected:NO];" which was wrong on so many levels.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
Hopefully that helps others that have this issue. Case closed.
You can use following while creating cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = Your allocation.
cell.selectionStyle = UITableViewCellSelectionStyleNone;
I guess you need to also please have look at the UIViewTable Property for Touch i.e. Delay Content Touches and Cancellable Content Touches.
Hope this helps.
Override -tableView:willSelectRowAtIndexPath: in your UITableView delegate, and return nil for everything just to make sure you're not allowing it to select the rows.