I have a UITableView which is using custom UITableViewCells to display some information. I'd like to add a UITableViewCellAccessoryDisclosureIndicator to the cells.
Every method that I try successfully adds the chevron, but once the table view scrolls down, they disappear. I'm doing the standard dequeueReusableCellWithIdentifier method, and when I dump out the references to the cells, it's re-using them properly. All of the other data displays fine, it's only the chevrons that disappear.
Things I've tried:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
accessoryTypeForRowWithIndexPath:
Anyone ever have this happen?
It could happen because you are setting your accessory type outside of the cached cell test:
static NSString *CellIdentifier = #"UIDocumentationCell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
[cell setText:mytext];
The better way, IMHO is like this:
static NSString *CellIdentifier = #"UIDocumentationCell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[cell setText:mytext];
Cocoa Touch doesn't seem to want to modify the cached instance of the cell ( subviews ) setting the disclosure indicator in the cell set method results in the indicator being cached, and redrawn once the cell appears again.
Related
I have created a TableView(Grouped Table View). And I can list the items in the table view. But I want to know how the below table is displayed
Like Calender is in the left side, and Gregorian in the Right Side ?? How that Gregorian is displayed in the Right Side ?? Is it a Custom TableView, Can anyone help me how to achieve that ?
Those are just regular cells with style = UITableViewCellStyleValue1 and also accessoryType = UITableViewCellAccessoryDisclosureIndicator.
To make one programmatically:
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"YourIdentifier"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
(Note that in real life you would probably try to dequeueReusableCellWithIdentifier:, and only create a new cell if that returns nil.)
Or, if you're working with IB, set "Style" to "Right Detail" and "Accessory" to "Disclosure Indicator".
You need to use following code helping to you
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
UIImageView *v = [[[UIImageView alloc] init]autorelease];
v.backgroundColor = [UIColor clearColor]; // put clear color
[v setClipsToBounds:YES];
cell.selectedBackgroundView = v;
[cell setClipsToBounds:YES];
}
UIImageView *imgVBG=(UIImageView*)[cell selectedBackgroundView];
if(indexPath.row==0){
imgVBG.image=[UIImage imageNamed:#"TopImg.png"];
} else if((indexPath.section==0 && indexPath.row==4)||(indexPath.section==1 && indexPath.row==7)){
imgVBG.image=[UIImage imageNamed:#"BottomImg.png"];
} else {
imgVBG.image=[UIImage imageNamed:#"MiddleImg.png"];
}
}
Here is your answer UITableViewCell with UITableViewCellStyleValue1, adding new line to detailTextLabel at cell at bottom
Can anyone please tell me what is the correct way to manage UITableView if I have a big number of cells? The interface of each cell depends on sections (each cell keeps different UI elements in its content view). I do not want to use reusable cells as it messes up with overlapping.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault nil] autorelease];
} else {
cell = nil;
[cell release];
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault nil] autorelease];
}
No, your code is not correct. First of all, it wouldn't even compile because [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault nil] is not valid syntax. Secondly, the [cell release]; line has no effect (which is good because if it had, it would be wrong) but its presence shows that you haven't understood the memory management concepts (yet).
Thirdly and most importantly, you should definitely use the table view's cell reuse, especially if you have a big table. If you have different types of cells, just use different reuse identifiers for them, no problem. The table view will then create multiple reuse pools and always return a cell of the type you ask it for in dequeueReusableCellWithIdentifier:.
I'm using reusable cells in my app. The method I'm using is as follows:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [yourArray objectAtIndex:row];
return cell;
}
It works fine.
Without reuseIdentfier you will run out of memory fast and tableview will scroll slow. You should change content of cells in this method, e.g. titles, images, etc. but not views. So create subclasses of cell for every section you need. Setup their views and in this method setup content.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
} else {
cell.title = [_cellTitles objectAtIndex:indexPath.row];
cell.image = [_cellImages objectAtIndex:indexPath.section];
}
I have a list of cells in a table view where only the last cell has a disclosure indicator (it triggers an action). When I scroll down my list of cells everything works fine, but if I scroll back up oddly the disclosure indicator appears in other cells too. I can't really figure out where's the problem, any help?
Thanks,
Daniele
This is the part of code that is use:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
if(([myArray count]-1) == indexPath.row) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
that is not a bug: it is a feature ;) because the cells are being reused.
If your tableview contains 200 cells and your iphone is able to show 5 cells at the same time then you only have 5-6 instances of UITableViewCell. If you scroll down a cell gets the disclosure-button and if you scroll back the cell is being reused and as a result the disclosure-button is still there.
to solve your problem:
approach 1: not only set the disclosure-button on the last cell. you should also remove/unset it in other cells.
approach 2: it seems that the last cell is another type of cell in semantic. So choose a reuse-identifier for example: #"MyLastCell for the last cell and #"MyCell" for all other cells. As a result your tableview will only reuse cells of the same type (in your case: with/without disclosure-button)
edit 1: some sample-pseudo-code for approach 2 ;
edit 3: shorter solution for approach 2
static NSString *CellIdentifier = #"Cell";
static NSString *LastCellIdentifier = #"LastCell";
bool isLastRow = (indexPath.row == numRows-1);
NSString *usedCellIdentifier = isLastRow ? LastCellIdentifier : CellIdentifier;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: usedCellIdentifier];
if(!cell)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:usedCellIdentifier] autorelease];
if(isLastCell)
{
//do disclosure-stuff here. Or add a UIButton here
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton
}
}
edit 2: sample code for approach 1
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.accessoryType = (idexPath.row == numRows-1) ?
UITableViewCellAccessoryDetailDisclosureButton
: UITableViewCellAccessoryNone ;
As thomas said, you can use his code and you can add this:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
for the last cell (inside the if where you dequeue your last cell) and this:
cell.accessoryType = UITableViewCellAccessoryNone;
for other cells (inside the if where you dequeue other cells).
I haven't tried this code but it should work... ;)
try this
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
if(([myArray count]-1) == indexPath.row) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
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.
I have a small form (5 fields) in a grouped UITableView. Each UITextField is inside of a UITableView cell. When clicking in a textField, it brings up the keyboard, which then allows you to scroll some of the cells out of view, when you pull them back down, their content is erased.
Am I correct in assuming that they have been redrawn, so their content is gone? If so, what is the best way to prevent this? Since I only have 5 fields, do I have to redraw my cells when the are scrolled back into view?
I am reusing cells:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
You can have a separate array of you text fields and implement you cell creation callback like this:
-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
[[cell.contentView subviews] makeObjectsPerformSelector: #selector(removeFromSuperview)];
[cell.contentView addSubview: [textFieldsArray objectsAtIndex: indexPath.row]];
return cell;
}