I have UITableViewController which pop UIActionSheet when user click on a cell with accessoryType =UITableViewCellAccessoryDetailDisclosureButton;
Now the method -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { works fine, except, i dont know in which cell user clicked.
I could , for example, declare a property where I save selected cell in didSelectRowAtIndexPath:(NSIndexPath *)indexPath { but I think there must be a better way.
I usually set the action sheet's tag to be the index path's row, but that only works if you don't care about the section number. If you do need the section as well, creating a property would be the best way to go about it.
You could also mess with a category and associated objects, but for me personally that would be too involved.
If your table only have one section, you could store which row presented the action sheet in the tag, something like this.
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
NSString *title = [NSString stringWithFormat:#"Sheet for row %i", indexPath.row];
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:#"Option 1", #"Option 2", nil];
[sheet setTag:indexPath.row];
[sheet showInView:self.view];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
int row = actionSheet.tag;
NSLog(#"Selected actionSheet buttonIndex %i for row: %i", buttonIndex, row);
}
It's probably the easiest way, but I wouldn't say it's the best way to do it.
Implement this UITableView delegate method to get the index path of the cell when the accessory button is tapped:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
}
Related
I have method called
- (void)redeemOfferService
{
// in this method i want access OffersBoughtCellTableViewCell,
how to access tableview cell here ?
// want to update selected tableview cell values
// here i am getting selected cell details in selectedOfferBoughtObj which
is actually NSObject in that i am having five string values
i want show that values in my tableview cell how can i ?
//
}
The above method is calling from
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex
{
if(alertView.tag == 10)
{
if(buttonIndex == 0)
{
[self redeemOfferService];
}
}
}
and this method is calling when i tap on tableview cell i.e.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *logoutAlert = [[UIAlertView alloc]initWithTitle:#"Are you sure you want to redeem?" message:nil delegate:self cancelButtonTitle:#"Yes" otherButtonTitles:#"No", nil];
logoutAlert.tag = 10;
[logoutAlert show];
}
i know there is way, we can send sender from button click but i want in above scenario.
Use a global variable in your class NSIndexPath type and on selected store your selected indexpath
NSIndexPath *selectedIndexPath; //declare it as a global
After assign selected value in didSelect
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
UIAlertView *logoutAlert = [[UIAlertView alloc]initWithTitle:#"Are you sure you want to redeem?" message:nil delegate:self cancelButtonTitle:#"Yes" otherButtonTitles:#"No", nil];
logoutAlert.tag = 10;
[logoutAlert show];
selectedIndexPath = indexPath;
}
And change like this in your function
- (void)redeemOfferService
{
OffersBoughtCellTableViewCell * _selectedCell = [offersTableView cellForRowAtIndexPath:selectedIndexPath]; //Now Its your selected cell Try this .
}
It will work fine try once and revert back
You are surely updating the tableview from some NSMutableArray, meaning you are filling up your tableview with this array.
In your redeemOfferService method, change the value of that Object inside the NSMutableArray with which you are filling up the tableview.
Then call [self.tableviewName reloadData]
You can use the indexPathForSelectedRow property of UITableView to access selected indexPath.
- (void)redeemOfferService
{
OffersBoughtCellTableViewCell *selectedCell = (OffersBoughtCellTableViewCell *)[tableViewObject cellForRowAtIndexPath:offersTableView.indexPathForSelectedRow];
}
This gives you the selected OffersBoughtCellTableViewCell
Using the following delegate method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PLOTCheckinTableViewCell *cell = (PLOTCheckinTableViewCell *)[self.checkinsTableView dequeueReusableCellWithIdentifier:CheckinCellIdentifier forIndexPath:indexPath];
[cell setSwipeGestureWithView:crossView color:redColor mode:MCSwipeTableViewCellModeSwitch state:MCSwipeTableViewCellState2 completionBlock:^(MCSwipeTableViewCell *cell, MCSwipeTableViewCellState state, MCSwipeTableViewCellMode mode) {
self.indexPathToDelete = [tableView indexPathForCell:cell];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Delete?"
message:#"Are you sure your want to remove this checkin?"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[alertView show];
}];
}
Then inside the UIAlertView delegate method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
// No
if (buttonIndex == 0) {
}
// Yes
else {
PLOTCheckinTableViewCell *cell = (PLOTCheckinTableViewCell *)[self.checkinsTableView cellForRowAtIndexPath:self.indexPathToDelete];
[self.checkins removeObjectAtIndex:self.indexPathToDelete.row];
[self.checkinsTableView deleteRowsAtIndexPaths:#[self.indexPathToDelete] withRowAnimation:UITableViewRowAnimationFade];
self.indexPathToDelete = nil;
}
}
However, whenever I hit "Ok" in the alert view, the cell that's deleted is always the last one in the tableview, ie. not the cell the user actually swiped.
Is it something to do with the dequeuing?
Yes. You should not be referencing to your cell. Instead, try to reference to the actual object that caused the cell to exist (i.e. if this is a list of messages, the message that is displayed within that cell).
The cell object is being reused and the UIAlertView wont know about that. Even if you have 1000 items in your list, you are not going to have more than 20 cells. They are always going to be reused thorough your table view scrolling.
You should be looking into removing an element from your data source array instead of removing the cell itself. After removing the element, you can always reload your table view to visually reflect the elemnt removed state.
I have UITableView, in which if any row is selected i am storing some values. If any other row is selected i am displaying an alertView with warning that his previous selection will be gone. This alerView has 2 buttons YES and NO. If YES is selected go on to selecting the new row which is fine. But if no is selected i want reselect the previous row. I can post the code if asked. But it seems more of logical question than code oriented.
Thank you.
first store the clicked tableview index to your global variable in UITableView Delegate like below,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView==yourTableview) {
yourMemberVariable=[indexPath row];
}
}
then check yourMemberVariable in UIAlertView delegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 0)//OK button pressed
{
//do something
}else{
if(yourMemberVariable>someValue){ //perform your own conditions whatever
[myTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:yourMemberVariable inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
}
}
}
You want to know the last row selected ,you can do this by setting
tableView.remembersLastFocusedIndexPath = true
in viewDidLoad function.
and then calling
tableView.indexPathForSelectedRow
wherever required.
It's simple. Just save previous row into class member. Good luck!
Keep track of the last selected item. On the select delegate for the table, store what was selected in a variable accessible througout the class.
NSInteger selectedRow = 0;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = [indexPath row];
}
Now you know what element to select if NO is pressed in the UIAlertView delegate
[myTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:selectedRow inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop];
I have a small amount of code from which I want only a certain view controller to use. The view controller shares a class with another controller.
Is it possible to target the if statement based on the push segue identifier?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"Added to Routine!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
I do have a IF statement within my prepareForSegue: method but I wish to have one within my didSelectRowAtIndexPath:
if ([segue.identifier isEqualToString:#"ShowSightingDetails"])
I have looked around but can't see anything directly associated with this.
This should be something that is fairly simple I would of thought.
Add a property, something like #property (assign, nonatomic) BOOL shouldAlert; and set its value in prepareForSeague, then you can refer to it later.
I suppose you have specified different cell identifiers for your cells in your storyboard. You could get the cell in tableView:didSelectRowAtIndexPath: and check its reuseIdentifier. The Code could be something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier isEqualToString:#"Identifier1"]) {
// Do something
} else if ([cell.reuseIdentifier isEqualToString:#"Identifier2"]) {
// Do something different
}
}
I notice when I set MessageTableViewCell accessoryType =UITableViewCellAccessoryDetailDisclosureButton and I tab on the "arrow button" itself, the pop menu that is declared on didSelectRowAtIndexPath: don't show up??!!! it works fine if I tabbed on the other area of cell, except on the "arrow button" itself,
However, if I used UITableViewCellAccessoryDisclosureIndicator cell accessory type instead, it works fine, even if I tabbed on the arrow itself.
I wonder if this normal behavior, a bug, or I did something wrong.
I prefer UITableViewCellAccessoryDetailDisclosureButton because in my opinion its more clear when you want to get attention of user.
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString* CellIdentifier = #"MessageCellIdentifier";
MessageTableViewCell* cell = (MessageTableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = /*[*/[[MessageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] /*autorelease]*/;
}
CastNearAppDelegate *appDelegate = (CastNearAppDelegate *)[[UIApplication sharedApplication] delegate];
Message* message = [appDelegate.dataModel messageWithID: indexPath.row];
if (!message.isSentByUser)
{
cell.accessoryType =/*UITableViewCellAccessoryDetailDisclosureButton; */UITableViewCellAccessoryDisclosureIndicator;
}else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
message.bubbleSize = [SpeechBubbleView sizeForText:message.text];
[cell setMessage:message];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIActionSheet *popupQueryOptions = [[UIActionSheet alloc]
initWithTitle:#"Options for Blocking and Spam Reporting"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Block Sender"
otherButtonTitles:/*#"Block Sender",*/
#"Inappropriate Content",
/*#"Tell a Friend via Facebook",
#"Tell a Friend via Twitter",*/
nil];
popupQueryOptions.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[popupQueryOptions showInView:[UIApplication sharedApplication].keyWindow];
}
They are used for different things. The indicator is just an indicator whereas the button allows you to have a different action e.g. acting like a button.
UITableView has two possible methods that it will call on it's delegate when the cell is tapped.
When the row itself is tapped the following is called
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
When you tap on the accessory then the tableView calls
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
You can also wire these up independently in Interface Builder. So this behaviour is quite deliberate.
When you use the disclosure button, the delegate method tableView:accessoryButtonTappedForRowWithIndexPath: is called instead of tableView:didSelectRowAtIndexPath:.
The disclosure button is usually used for some kind of secondary action of a cell, e.g. in the Wifi settings, it shows options for a network, while tapping the entire cell connects to it.