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;
}
Related
I am new in iPhone development. I am using UItableview for showing list.
And able to show all items successfully.
But they changed when I scroll tableview.
Please help me.
Try this code in cellForRowAtIndexPath method of tableview
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
Please give me more information to show your case clearly.
Have a look at this function first because all rows are generated from here!
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
return cell;
}
Check whether each row is exist,unless just reuse it later.
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;
}
How to show a detail disclosure button to the uitableview without using the custom cell. I know its by using the accessoryType: method, but don't know how to implement that..pls help..
// Customize the appearance of table view cells.
- (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];
}
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
return cell;
}
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
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.