I have seen other questions on here related to this, but I have their solutions in place, and things still move around when I scroll.
Basically, I have a table of data and I want the first and only the first row to have a UITableViewCellAccessoryDisclosureIndicator. The problem is, when I scroll around, the indicator duplicates, deletes, and moves to other cells. Here is my code..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if(indexPath.row == 0) {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = [tabledata objectAtIndex:indexPath.row];
return cell;
}
The problem is something with the indexPath.row variable.. its somehow returning 0 in other cells that aren't the very first (when it comes to displaying cells). HOWEVER... the data is always right from my array(which implies the value HAS to be correct) and in my
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
method, i only wish to change screens when row 0 is clicked.. and regardless of where I have scrolled to, no cells trigger except the very first. So it seems THAT check is always correct while the one inside cellForRowAtIndexPath is not...
Most likely, you are re-using cells that already have the accessoryType set. You need to explicitly set it to NOT show on cells where it shouldn't.
if(indexPath.row == 0){
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
Related
I have a table with a few rows, and the place holder text for all is the same. How can I programmatically change the placeholder text of only the first one?
Thanks!
You need to run an if statement to check the index of the cell. 0 is the first index, so you would need to check to see if the row is 0.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
if (indexPath.row == 0)
cell.textLabel.text = #"First Cell";
else
cell.textLabel.text = #"Not First Cell";
}
In order to access your cell AFTER the cell was created/reused, try the - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath method of your uitableview object! See the following Apple doc for a detailed elaboration on this method.
Note:
Return Value
An object representing a cell of the table or nil if the cell is not
visible or indexPath is out of range.
Hey I'm having trouble trying to figure this one out. UITableView has a method [tableView reloadSections:(NSIndexSet *) withRowAnimation:(UITableViewRowAnimation)] now according to the Apple docs this method takes in an NSIndexSet object and reloads what ever section specified by the index set. The problem is even though im only sending in one section to this method it ends up reloading all the sections and i can't understand why this is happening. Any help will be greatly appreciated
Even if you try reloading only a section, you must also provide the populating process section by section:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"DetailViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
if (indexPath.section == 0){
//blablabla
cell.textLabel = blabla
}
else if (indexPath.section == 1){
///blablabla
cell.textLabel = blabla2
}
return cell;
}
... because reloading the table (is it only a section or the whole table) wil call the method above
I have a strange problem with my UITableView. I want all the cells in the table to be selectable, such that if a cell is selected, an appropriate action is executed. All the cells in my table are currently selectable apart from the cell at row 0 (the cell at that appears at the top of the table). This cell is not selectable, even though it has been set to allow for selection. Any ideas?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
tableView.allowsSelection = YES;
static NSString *SettingsTableID = #"SettingsTableID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SettingsTableID];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier: SettingsTableID] autorelease];
}
cell.textLabel.text = [tableHeadingsArray objectAtIndex:row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Many thanks.
Sorry everyone, I'm being stupid. :) This code was in my ViewController sub-class. I copied the class from an example, and forgot to check it over thoroughly before using it.
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSUInteger row = [indexPath row];
if (row == 0)
return nil;
return indexPath;
}
Deleting this has fixed the problem.
Cheers.
I am programing a UITableView to behave as an inclusive selection list. My table displays correctly and allows for multiple cells to be selected with check boxes. My problem is that cells which have been selected (cells contain a check mark to the right) loose their selected status when scrolled out of view (cells check mark disappears). I want the selections made to cells in the table to be preserved even if cells are scrolled out of view. Does anyone have any idea what is causing this?
Here is my code inside of my TableViewController class:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [widgetTitles_glob objectAtIndex:row];
cell.detailTextLabel.text = #"";
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:YES];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
// Reflect selection in data model
} else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
// Reflect deselection in data model
}
}
Any help would be very much appreciated.
When you are using UITableView correctly, only as many UITableViewCell instances are allocated as are needed to fit on the screen. When you scroll down a table, and a cell disappears off the top of the screen, it is relocated to the bottom.
Your delegate method, tableView:cellForRowAtIndexPath: is responsible for setting up a cell, either creating a new one or reconfiguring a recycled one.
The proper thing to do is use an array to store your checked/unchecked values. When didSelectRowAtIndexPath: is called, you update the cell and your array. When tableView:cellForRowAtIndexPath: is called, you configure the cell based on the values in the array.
Based on your comments, you are already doing the right thing in didSelectRowAtIndexPath:; you just need to use those values when you set up the cell instance, because that cell could represent a row that has already been checked. Check the array and then set cell.accessoryType accordingly.
In cellForRowAtIndexPath: you were assigining the accessoryType as none, so whenever you scroll that delegate is called and set the accessory type as none. So you should change your code.
I have also faced this problem once; I came up with a solution as follows.
Store the indexPath.row values of selected indexPath in an array (this code should be in didSelectRowAtIndexPath delegate) if it is deselected remove from that array. In cellForRowAtIndexPath: method I have used a for loop and check if that indexPath.row is present then change it's accessory type to checkmark else none.
Thanks for your help. It actually turns out that the reason why the cells were getting reset to UITableViewCellAccessoryNone was becasue of the following line of code inside of cellForRowAtindexPath:
cell.accessoryType = UITableViewCellAccessoryNone;
Removing this has fixed the table.
I have this bizarre problem. I'm making a checklist program with XCode and I'm using UITableView with UITableViewCellAccessoryCheckmark. I can select cells and the checkmark will appear, but somehow, other cells that I have NOT yet selected below will also have a checkmark appear. Any ideas?
Here's my check mark coding:
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
cell = [aTableView cellForRowAtIndexPath: indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
I don't know if this affects it, but I also implemented this method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Configure the cell.
if(tableView == Table1){
switch(indexPath.section){
case 0:
cell.textLabel.text = [array1 objectAtIndex:indexPath.row];
break;
case 1:
cell.textLabel.text = [array2 objectAtIndex:indexPath.row];
break;
case 2:
cell.textLabel.text = [array3 objectAtIndex:indexPath.row];
break;
}
//cell.textLabel.text = [NSString stringWithFormat:#"Row %d", indexPath.row];
}
if(tableView == Table2){
cell.textLabel.text = [array4 objectAtIndex:indexPath.row];
}
return cell;
}
Thanks.
Set the cell.accessoryType each time you call tableView:cellForRowAtIndexPath:. Otherwise, when you reuse a cell, you'll get it's accessoryView instead of what you're expecting.
So, yeah, you'll need to keep track in when NSIndexPaths are selected by some method other than just looking at the accessoryType.
You should keep the checked/unchecked info in data source (array).
I also advise you to remove the cell.accessoryType = UITableViewCellAccessoryNone; line.
This line will be executed only for few first cells. All the other cells will be "reused" - meaning that the old (already initiated) cells will be used, and you will have to modify the details that are displayed on these cells (all inside cellForRowAtIndexPath as you do now).
In addition you will have to add a similar line (something like cell.accessoryType = ([[array objectAtIndex:indexPath.row] boolValue] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;).
In general, I suggest you to use one array for holding the data for your table, when each item in the array will be a dictionary. This way you will be able to hold the texts and the boolean checkmarks (inside NSNumber) and easily access them when needed.