I am using UITableview in my project, and also i have UITableviewcell for that UITableview. The problem is that cells are getting reused.if it get reused, when i select button i want the image to be changed for single cell and button isSelected =YES. So the button's selected image is getting reuse for every cell.
So,kindly help me out with this problem .
// In indexPathRow before return
cell button.tag=indexPath.row;
In buttonclick action
//
-(IBAction)BtnAction:(UIControl *)sender
{
UIButton *button = (UIButton*)sender;
NSIndexPath *buttonIP = [NSIndexPath indexPathForRow:sender.tag];
//Type cast it to CustomCell
CustomCell *cell = (CustomCell*)[table cellForRowAtIndexPath:buttonIP];
if(button.isSelected==NO)
{
cell.Imageview.image=selectedImage;
button.isSelected=YES;
}
else
{
cell.Imageview.image=OldImage;
button.isSelected=NO;
}
[table reloaddata];
}
insted of using the above code you can use this line of code
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(firstTime)
{
[tableView cellForRowAtIndexPath:indexPath].imageView.image = [UIImage imageNamed:#"selected image"];
[attatancearry addObject:value];
}
if(secondTime)
{
[tableView cellForRowAtIndexPath:indexPath].imageView.image = [UIImage imageNamed:#"absent image"];
[attatancearry removeObject:value];
}
}
and add the value to an another nsmutablearry as the attendence is added and when you press the same cell again you have to remove the value from the nsmutablearray you have added before, and reset the image back to absent. but you don't have to reload the entire tableview it will just change the cell which you have select right now. as your adding the value or index number of the cell into a array you can use the selection value for further use.
you have to see the cell which you have selected, and set a flag value as the selected index. and reload the table.
when you reload the table check the flag value and set the image which you want to set for the cell which is selected. it will give you different cell selection.
for example
int selectionFlag = -888;
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(selectionFlag == indexPath.row)
{
//set the image you want to set for the cell which is selected.
}
else
{
//the normal image you want to set.
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectionFlag = indexPath.row;
[tableView realoadData];
}
Related
I have a setting screen that is a UITableView with rows of settings. When user open that screen I load stored settings and filled to UITextField etc... Everything was fine.
But there are some of the checkmark settings, I've been trying to check this in programmatically way but is not work, here is my code:
-(void)viewDidAppear:(BOOL)animated{
[self LoadCurrentRecord];
if(_previousValid)
{
NSIndexPath *regionFromData = [NSIndexPath indexPathForRow:_regionAutoCheck inSection:3];
[self.tableView cellForRowAtIndexPath:regionFromData].accessoryType = UITableViewCellAccessoryCheckmark;
}
[self.tableView reloadData];
}
In fact, I can see data can load by check to this category but I didn't see checkmark icon.
Any idea?
You must need to set it in this method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell; // Create Cell
if(_previousValid && indexPath.row == _regionAutoCheck && indexPath.section == 3 )
{
// SET CHECKMARK
} else {
// SET NONE
}
}
Here is how you should work with table- and collectionViews:
Have a collection of dedicated data-elements for each of which a cell will be used to display its data. In your case this would be some kind of Region object.
Implement the table/collectionview datasource methods that return number of cells in section and number of sections based on that collection.
Make sure you configure each cell ONLY in -tableView:cellForRowAtIndexPath: / -collectionView:cellForItemAtIndexPath:, just like PKT's answer. This cell might be reused, so assume any changes you made to this type of cell you need to update here.
When data changes, create an indexPath for the object that changes based on its position in the collection from 1. Then call '-reloadRowAtIndexPath:'/ -reloadItemAtIndexPath for that object. This will cause the tableView/collectionView to call -tableViewcellForRowAtIndexPath:/-`collectionView:cellForItemAtIndexPath:' again. As this method now contains the logic for configuring the cell based on your data-object, everything is in sync.
I can't stress enough how important 1. is. Simplest example is: each section is an array of data objects. If you have multiple sections, you can add each array to another array:
// one section:
NSArray *myData =
#[
#[dataItem1, dataItem2, dataItem3]
#[dataItem4, dataItem5, dataItem6]
];
- (NSUInteger) numberOfSectionsInTableView: (UITableView *) tableView
{
return myData.count;
}
- (NSUInteger) tableView: (UITableView *) tableView numnberOfRowsInSection: (NSUInteger) section
{
NSArray *dataForSection = myData[section];
return dataForSection.count;
}
- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath:
{
NSArray *dataForSection = myData[indexPath.section];
MyObject *dataObject = dataForSection[indexPath.row];
NSString * cellID = #"myCellID";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: cellID];
if (nil == cell)
{
// create a cell
// ...
}
// configure the cell based on the data object
if (dataObject.isBlue)
{
cell.contentView.backgroundColor = [UIColor blueColor];
}
else
{
// N.B.! don't forget the else clause, as cells are reused, so this
// cell might be recycled from a cell that was used to display
// the data of a blue data object before.
cell.contentView.backgroundColor = [UIColor blueColor];
}
return cell;
}
Finally, I've found a really simple solution for this case.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == _regionAutoCheck && indexPath.section == 3)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone; // for other cases remove it
}
}
UPDATE
After that, add [self.tableView reloadData]; into -(void)viewDidAppear:(BOOL)animated and you will see it works.
That's all.
Thanks all for help
I am trying to update a specific dynamic cells font size from a -(void) method or some way without using cellForRowAtIndexPath. Is this possible?
Thanks
If you know the position of the index, as follows:
First create indexPath by row at position:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
Then access to cell:
MyCell *cell = (MyCell *)[self.tableView cellForRowAtIndexPath:indexPath];
Call
[self.view.tableView reloadRowsAtIndexPaths:#[your_index_path] withRowAnimation:UITableViewRowAnimationAutomatic];
inside your method. that will cause row update
You can not update a cell without having a call to: cellForRowAtIndexPath.
When you want to update font size in a cell, then reload the cell. In your cellForRowAtIndexPath method add a conditional statement to check the indexPath of the cell you want a different font size and edit different font size. Do not forget to add else condition so that when the cell reloads it will make the font size normal for other cells.
However if you want somehow. Then you can use global reference variable to the cell. But this will only work if the cell is displaying on screen.
Here is the example code:
#interface TableViewController ()
{
UITableViewCell *aCell;
}
#end
#implementation TableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *theCell = [tableView dequeueReusableCellWithIdentifier:#"TableViewCellIdentifier" forIndexPath:indexPath];
if(indexPath.row == SPECIFIC_ROW_NUMBER){
aCell = theCell;
theCell.tag = SPECIFIC_ROW_NUMBER;
}else if (theCell.tag == SPECIFIC_ROW_NUMBER){
// If the cell is dequeued
aCell = nil;
theCell.tag = 99999; // some unused row number
}
}
- (void)someMethod {
if(theCell != nil){
aCell.titleLabel.font = NEW_FONT;
}
}
#end
I'm playing with the cell identifier in a TableviewController, I'm using storyBoard with dynamic cells.
I set 2 cells with 2 identifiers and used a custom row height:
In my viewDidLoad, I just insert some checking information to a mutableArray:
- (void)viewDidLoad
{
[super viewDidLoad];
_arrayCellContent = [[NSMutableArray alloc]init];
for (int i=0; i<15; i++) {
if (i%2 == 0) {
[_arrayCellContent addObject:#"white"];
}
else
[_arrayCellContent addObject:#"Brown"];
}
}
My cellForRow delegate method is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* identifierCellSlim = #"cellSlim";
static NSString* identifierCellFat = #"cellFat";
UITableViewCell *cellSlim = [tableView dequeueReusableCellWithIdentifier:identifierCellSlim forIndexPath:indexPath];
UITableViewCell *cellFat = [tableView dequeueReusableCellWithIdentifier:identifierCellFat forIndexPath:indexPath];
if (indexPath.row%2 ==0) {
cellSlim.textLabel.text = self.arrayCellContent[indexPath.row];
return cellSlim;
}
// Configure the cell...
else {
cellFat.textLabel.text = self.arrayCellContent[indexPath.row];
cellFat.detailTextLabel.text = #"yalla";
return cellFat;
}
}
The final outcome is:
Even cell row heights, not costumed. Why is that? (I know I might work it out with the right delegate method, but I just want to know why the IB not doing his job)
Also in the beginning the cells appear to be in the right color but when I click some of them they will transform to the other cell,
Does clicking the cell change the indexPath ?
Example:
You are dequeuing both cells in the same method call.
You should check for which cell is necessary for the given NSIndexPath and dequeue the relevant cell.
I have a UITableView and I am trying to get the text of all the selected rows when a button is pressed. Here's what I have so far:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
[selectedRows addObject:selectedCell.textLabel.text];
}
selectedRows is an array.
Here is my button press function where I need access to the checked row titles:
- (IBAction)selectList:(id)sender {
NSLog(#"%#", selectedRows);
}
This doesn't work for me because if a user unchecks a row and then clicks the submit button - it is not reflected in the array. I would appreciate some help with this. thanks.
Instead of dealing with keeping tabs on what is/isn't selected at any given moment, why not just wait until it's time to select the list to generate it and let the table keep track of what's selected. (provided it isn't some massive amount of data) You could loop through the index paths of your table's selected cells and pull the string you're looking for directly out of the datasource.
- (IBAction)selectList:(id)sender
{
NSMutableArray *arrayOfText = [NSMutableArray new];
for (NSIndexPath *idx in self.tableView.indexPathsForSelectedRows) {
[arrayOfText addObject:dataSource[idx.row]];
}
NSLog(#"%#",arrayOfText);
}
You could add a didDeselectRowAtIndexPath function and remove the item from the array.
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
[selectedRows removeObject:selectedCell.textLabel.text];
}
I have a UITableView where the user should be able to select (check) multiple rows.
I have an NSMutableArray in my controller to hold the selected items, and in my cellForRowAtIndexPath method, I check whether the item is in that array and return the cell in a checked/unchecked state accordingly.
Here's the code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = kContactCellReuseIdentifier;
static NSString *searchIdentifier = kContactSearchCellReuseIdentifier;
POContactCell *cell;
// Configure the cell...
if (tableView == self.tableView) {
cell = (POContactCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.contact = self.contacts[indexPath.row];
NSLog(#"Returned cell with name %#", cell.contact.name);
} else {
cell = (POContactCell*)[tableView dequeueReusableCellWithIdentifier:searchIdentifier forIndexPath:indexPath];
cell.contact = self.searchResults[indexPath.row];
}
if ([self.selectedContacts containsObject:cell.contact])
{
NSLog(#"was checked");
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
cell.accessoryType = UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
POContactCell* tappedCell = (POContactCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];
NSLog(#"Selected contact %#", tappedCell.contact.name);
if ([self.selectedContacts containsObject:tappedCell.contact]) {
// cell is already selected, so deselect it
NSLog(#"It's already selected, so deselect it");
[self.selectedContacts removeObject:tappedCell.contact];
tappedCell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
NSLog(#"It's not already selected, so select it");
[self.selectedContacts addObject:tappedCell.contact];
tappedCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:NO];
}
This code works... except for the first selection. The first cell that the user taps will get checked and will never get unchecked. I see from the log statements that all the cells are going through the exact same process and it's correctly recognizing the selection state of the first tapped row too, even though the accessory view doesn't reflect it.
After the first selection, all the other rows work perfectly.
Any debugging ideas?
You should be putting self.contacts[indexPath.row] (or self.searchResults[indexPath.row], as appropriate) in your array of selected items, and checking whether or not those objects exist or not in the array when the user taps a cell. You are almost doing that, it would appear, by setting cell.contact to the object from your data source and checking for cell.contact in your array. But I'd try putting the object directly into your array, e.g.
id contact = self.contacts[indexPath.row];
if ([self.selectedContacs containsObject:contact])
...
and stop checking if cell.contact is in the array to determine "selected-ness".
In a UITableView there is a small set of actual UITableViewCell objects in memory, and they get re-used. The root of your problem could very well be this, because you are checking to see if cell.contact is in your set of selected items; when a cell is reused, unless you wrote your own prepareForReuse, the previous value of your custom attributes may not (likely will not) be cleared.
Does that make sense?