When I tap on a table view cell I need to change another cell's detail label text.
How can I do this?
You need to stored indexPath for selected row. You can put a condition in cellForRow about same.
Here is sort example:
Declare variable in .h file:
int selectedIndexPath;
.m
-(void)viewDidLoad
{
[super viewDidLoad];
// So it won't show any select for the first time
selectedIndexPath = -1;
[tableView reloadData];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
int currentRow = (int)indexPath.row;
if(currentRow == selectedIndexPath)
{
// Show your base cell
}
else
{
// Show detail cell
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedIndexPath = (int)indexPath.row;
[tableView reloadData];
}
Related
I am developing Iphone Application.Using Three table view on Single viewcontroller. value show on those tableview's on single array but problem is that those array value show on first tableview not on other two tableview's. please help Thanks in advance
code..
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_arrayResult count];
}
- (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];
}
MEObject *obj = [_arrayResult objectAtIndex:indexPath.row];
if (tableView == _tableView) {
cell.textLabel.text= obj.emp_client_name;
}
if (tableView == _secondTableView) {
cell.textLabel.text= obj.emp_event_name;
}
if (tableView == _thirdTableView) {
cell.textLabel.text=obj.emp_client_name;
}
return cell;
}
Please cross check if you are setting datasource and delegates of all 3 tables to viewcontroller.
When you set your _arrayResult, you need to reload all 3 table view
_arrayResult = #[a,b,c];
[table1 reloadData];
[table2 reloadData];
[table3 reloadData];
After once you set the datasource/Delegate to the all three tableview. I haven't seen any datasource allocation as per your tableview. Like
if tableview == tableview1 {
Return first array
}
Can you please try giving name to those tableview on outlet and then for each datasource and delegates function call as per your requirement but before check which tableview is displayed.
This is a little hard to explain, but I will try my best. The code below is just some simple code I put together to demonstrate my problem better. When a user selects the second cell (row) for example, the tableview properly changes the cell with this [cell selected:YES]; when tableview reloads. If the second cell is selected and my tableview reloads with more new cells, the wrong cell is selected. The previous selected second cell becomes the fourth or fifth cell when the tableview updates, but the second cell is still selected.
I know this is because of selectIndexPath index row is two. Is there a way around this?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
FriendCell *cell
if (selectedIndexPath.row == indexPath.row )
[cell selected:YES];
else
[cell selected:NO];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
selectIndexPath = indexPath;
}
If your source array can changed (add/remove elements) then you have to keep track of the selected item, not the selected index. You haven't shown what your data source object is, but let's say it was an array of strings:
#property (strong,nonatomic) NSMutableArray *tableData;
#property (strong,nonatomic) NSString *selectedItem;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
FriendCell *cell
if (self.selectedItem != nil && [self.tableData[indexPath.row] isEqualToString:self.selectedItem]) {
[cell selected:YES];
} else {
[cell selected:NO];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedItem = self.tableData[indexPath.row];
}
I have a tableview which can be expanded on selecting the cell and collapses on selecting again. When you select, the cell should expand and display a label and when you select again it collapses and hides the label . The expanding and collapsing works fine, but if i scroll the tableview after expanding a cell it behaves weird. Once it goes out of the view and comes back , the cell will have the expanded cell's height but the label which is supposed to be shown in expanded cell is hidden.If i select the cell again it collapses and displays the label. I use ,
- (CGFloat)tableView:(UITableView *)t heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:t cellForRowAtIndexPath:indexPath];
if([self cellIsSelected:indexPath])
return cell.frame.size.height+35;
return cell.frame.size.height;
}
- (BOOL)cellIsSelected:(NSIndexPath *)indexPath {
// Return whether the cell at the specified index path is selected or not
NSNumber *selectedIndex = [self.selectedIndexes objectForKey:indexPath];
return selectedIndex == nil ? FALSE : [selectedIndex boolValue];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Deselect cell
NSLog(#"Select cell:%#",indexPath);
[self.tableView deselectRowAtIndexPath:indexPath animated:TRUE];
if([self pickTaskForIndexPath:indexPath].productSpecialMessage){
BOOL isSelected = ![self cellIsSelected:indexPath];
NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
[self.selectedIndexes setObject:selectedIndex forKey:indexPath];
PickTaskTableviewCell *cell= [self.tableView cellForRowAtIndexPath:indexPath];
cell.message.hidden=false;
cell.messageLabel.text=[self pickTaskForIndexPath:indexPath].productSpecialMessage;
cell.messageLabel.lineBreakMode=NSLineBreakByTruncatingTail;
cell.messageLabel.numberOfLines=3;
if(cell.messageLabel.hidden==true){
cell.messageLabel.hidden = false;
} else {
cell.messageLabel.hidden = true;
}
NSLog(#"message:%#",cell.messageLabel.text);
[cell layoutIfNeeded];
}
self.tableView.rowHeight=UITableViewAutomaticDimension;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
indexPath is added to the selectedIndexes on didSelectRowAtIndexPath
Please help me
Cells should be configured only within cellForRowAtIndexPath. When a state change occurs that makes a cell need to look different, just reload that cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PickTaskTableviewCell *cell = (PickTaskTableviewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
// everything else you do to configure the cell goes here, then ...
// check the logic here, we want one condition that tells us whether to show the labels
if([[self cellIsSelected:indexPath] && self pickTaskForIndexPath:indexPath].productSpecialMessage){
// don't need these here
//NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
// [self.selectedIndexes setObject:selectedIndex forKey:indexPath];
// PickTaskTableviewCell *cell= [self.tableView cellForRowAtIndexPath:indexPath];
cell.message.hidden=false;
cell.messageLabel.text=[self pickTaskForIndexPath:indexPath].productSpecialMessage;
cell.messageLabel.lineBreakMode=NSLineBreakByTruncatingTail;
cell.messageLabel.numberOfLines=3;
cell.messageLabel.hidden=NO;
} else {
cell.message.hidden=YES;
cell.messageLabel.hidden=YES;
}
NSLog(#"message:%#",cell.messageLabel.text);
// don't need this here
// [cell layoutIfNeeded];
return cell;
}
Selection (and presumably deselection) cause the need to update the cell, so...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// don't deselect it here, just reload it
// more on this later...
[self.selectedIndexes setObject:selectedIndex forKey:indexPath];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
// probably do the same in didDeselectRowAtIndexPath:
One last (optional) point. There's no need to maintain your own list of selected index paths, UITableView does that for you, so you could delete your selectedIndexes property and just use the table view methods, e.g....
- (BOOL)cellIsSelected:(NSIndexPath *)indexPath {
// Return whether the cell at the specified index path is selected or not
return [[self.tableView indexPathsForSelectedRows] containsObject:indexPath];
}
I am new at objective-c coding. I was trying to implement a check mark on a table view controller. I want check mark to seen when i click on a cell, and disappear when i re-click on that cell.
For example i found this code below. But i don't understand one thing clearly. What does "data" and "checkData" means ? Do we have to set them before that code ?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// do usual stuff here including getting the cell
// determine the data from the IndexPath.row
if (data == self.checkedData)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell; }
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// determine the selected data from the IndexPath.row
if (data != self.checkedData) {
self.checkedData = data;
}
[tableView reloadData]; }
So I was searching for some codes and i couldn't find any code as i want.
I will be very happy for any help.
Thanks.
The code you posted is not good for general purposes.
To support multiple cell selections, you need an extra data structure (e.g. an array of booleans or an NSIndexSet) to keep track of the selected indexes. And then, as soon as you get the tableView:didSelectRowAtindexPath: update the data structure and force the reload of the table, i.e. [self.tableView reloadData] in order to show/hide selection checkmarks
Some chunks of code
#implementation TableViewController {
NSArray * _data;
NSMutableIndexSet *_selectedIndexes;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
...
self.selectedIndexes = [[NSMutableIndexSet alloc] init];
...
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([_selectedIndexes containsIndex:indexPath.row]) {
[_selectedIndexes removeIndex:indexPath.row];
} else {
[_selectedIndexes addIndex:indexPath.row];
}
[tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
....
if ([_selectedIndexes containsIndex:indexPath.row])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
...
return cell;
}
Note that NSMutableIdexSet must have the same length of NSArray representing the data structure you're using to populate tableView's cells.
Alternatively, as I said, you could use an array of BOOL.
Create a property that hold the selected index:
#property (nonatomic, assign) NSInteger selectedIndex;
Then:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.selectedIndex == indexPath.row) {
self.selectedIndex = -1;
} else {
self.selectedIndex = indexPath.row;
}
[tableView reloadData];
}
And present the checkmark:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// do usual stuff here including getting the cell
if (indexPath.row == self.selectedIndex) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
There are a couple ways you can support a checkmark on a table cell. This example code seems to be assuming that you only have one checked cell in your table view, and tapping a different cell would move the checkmark to that other cell.
Basically, checkedData would be a property on your class (typically you would be using a subclass of UITableViewController, but it doesn't need to be, as long as your class conforms to both UITableViewDataSource and UITableViewDelegate). The data variable is derived from the selected row.
Here's one way you could fill in the gaps:
YourClass.h
// ...
#property int checkedIndex;
// ...
YourClass.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// do usual stuff here including getting the cell
// See if this row is the checked row
int thisRowIndex = indexPath.row;
if (thisRowIndex == self.checkedIndex)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the selected data from the IndexPath.row
int thisRowIndex = indexPath.row;
if (thisRowIndex != self.checkedData) {
self.checkedIndex = thisRowIndex;
}
[tableView reloadData];
}
Of course, this doesn't really solve your problem. Since you want the cell to toggle, you will need to keep a record of which cells are on and which are off. If you're only toggling one or two cells, you could get away with having one or two BOOL properties on your class which represent the state of each cell. If you have a larger number of cells that you want to toggle, you should store the state of each cell in an NSMutableArray, and get/set the values that match up with each index.
YourClass.h
// ...
{
NSMutableArray *_checkedRows; // This is an instance variable, not a property.
}
// ...
YourClass.m
// ================================================================
// Don't forget to initialize _checkedRows in your [init] method!!!
// ================================================================
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// do usual stuff here including getting the cell
// See if this row is the checked row
BOOL rowIsChecked = [[_checkedRows objectAtIndex:indexPath.row] boolValue];
if (rowIsChecked)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// determine the selected data from the IndexPath.row
// Set the state of the cell to the opposite of what it currently is.
BOOL rowIsChecked = [[_checkedRows objectAtIndex:indexPath.row] boolValue];
[_checkedRows replaceObjectAtIndex:indexPath.row
withObject:[NSNumber numberWithBool:!rowIsChecked]];
[tableView reloadData];
}
I have a UITableViewController that toggles into its editing mode when the user presses a button in the toolbar. I want the user to select multiple cells and then put a rounded red checkmark on the left side of each selected cell. I've selected Multiple Selection During Editing in the table view in Storyboard and no accessory / editing accessory for my custom cell.
The problem is that I can find each tapped cell in the tableView's indexPathsForSelectedRows, but the red checkmark on the left of each selected cell doesn't appear. However, after leaving editing mode, each selected cell shows a checkmark accessory on the right (which I don't need anymore after finishing editing).
While editing:
After editing:
Here is what I did in code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.editing)
{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone)
{
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
}
else
{
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
}
}
}
and
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
if (tableView.editing)
{
cell.accessoryType = UITableViewCellAccessoryNone;
for (NSIndexPath *selectedIndex in [self.tableView indexPathsForSelectedRows])
{
if ([selectedIndex isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
break;
}
}
}
...
Thanks!
If anyone comes across the same issue, here is a snipped of how I've solved it. I have a toolbar button connected to an IBAction that toggles the UITableView's editing mode. When editing is enabled, the user can select rows and hit a delete button which has the number of selected rows set in its label.
#interface TableViewController ()
{
NSMutableArray *selectedCellRows; // Used to remember which cells have been selected during editing mode
}
- (IBAction)toggleEditing:(id)sender;
#end
#implementation TableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GeneralReservationCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CELL_IDENTIFIER];
// Set up the cell...
[self configureCell:cell forTableView:tableView atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(GeneralReservationCell *)cell forTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{
// Basic layout
cell.nameLabel.text = #"Some text";
cell.selected = NO;
if (tableView.editing)
{
for (NSIndexPath *selectedIndex in selectedCellRows)
{
if ([selectedIndex isEqual:indexPath])
{
cell.selected = YES;
break;
}
}
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.editing)
{
[selectedCellRows addObject:indexPath];
[self updateEditingToolbarButton];
}
else
{
// Do whatever you do normally when the cell gets selected
}
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.tableView.editing)
{
[selectedCellRows removeObject:indexPath];
[self updateEditingToolbarButton];
}
}
- (void)updateEditingToolbarButton
{
int selectedRows = [self.tableView.indexPathsForSelectedRows count];
if (selectedRows == 0)
{
[deleteBarButton setTitle:#"delete"];
deleteBarButton.enabled = NO;
}
else
{
[deleteBarButton setTitle:[NSString stringWithFormat:#"delete (%d)", selectedRows]];
deleteBarButton.enabled = YES;
}
}
#pragma mark - IBActions
- (IBAction)toggleEditing:(id)sender
{
if(self.tableView.editing)
{
[self.tableView setEditing:NO animated:YES];
[selectedCellRows removeAllObjects];
[self showToolbarInEditingMode:NO];
}
else
{
[self.tableView setEditing:YES animated:YES];
[self showToolbarInEditingMode:YES];
}
}
#end
Additionally, I set the Editing Accessory to none in Interface Builder.
If you want the rounded circle to be filled when the cell is checked, you need to set the cell's selectionStyle to other than none.
cell.selectionStyle = .blue
This can also be set in the interface builder.
Also you if you don't want the checkmark when not editing the tableView, you need to set the cell's accessoryType to .none in your else block.
if tableView.isEditing {
...
} else {
cell.accessoryType = .none
}