Reputation: 1071
I understand this is suppose to happen but I haven't been able to find a way to call this method when the button is tapped The method gets called but the wrong cell is selected.
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
_postCell = (postCell *) [self.tableView dequeueReusableCellWithIdentifier:@"postCell"];
_postCell.personStringPost.text = [object objectForKey:@"stringPost"];
[_postCell.nameLabel setTitle:[object objectForKey:@"User_Name"] forState:UIControlStateNormal];
_postCell.userId = [object objectForKey:@"userId"];
_postCell.selectionStyle = UITableViewCellSelectionStyleNone;
PFFile *imageFile = [object objectForKey:@"profileImage"];
NSData *data = [imageFile getData];
_postCell.profileImage.image = [UIImage imageWithData:data];
[_postCell.nameLabel addTarget:self action:@selector(personProfile:tableView:) forControlEvents: UIControlEventTouchUpInside];
[_postCell.profileImageButton addTarget:self action:@selector(personProfile:tableView:) forControlEvents:UIControlEventTouchUpInside];
return _postCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
postCell *cell = (postCell *)[tableView cellForRowAtIndexPath:indexPath];
self.userId = cell.userId;
NSLog(@"Did Select: %@", self.userId);
}
- (void) personProfile: (NSIndexPath *) indexPath tableView: (UITableView *) tableView{
[self tableView:tableView didSelectRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:@"personProfile" sender:self];
}
Upvotes: 1
Views: 3205
Reputation: 13652
This is basically pbasdf answer above with Swift 3
I do call didSelectRowAt directly since it is not triggered by selectRowAtIndexPath
The tag is set on cell creation with the row of the indexpath
The getTableView function is my own
@IBAction func actionButtonPushed(_ sender: Any) {
guard let button = sender as? UIButton else { return }
guard let tableView = getTableView() else { return }
let indexPath = IndexPath(row: button.tag, section: 0)
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
if let delegate = tableView.delegate {
delegate.tableView!(tableView, didSelectRowAt: indexPath)
}
}
Upvotes: 0
Reputation: 637
Few things i hope it will help
while dealing with button with only one section
in cellfor row method
yourcell.mybutton.tag=indexPath.row;
-(void)myCellbuttonAction:(id)sender
{
UIButton *button = (UIButton *)sender; // first, cast the sender to UIButton
NSInteger row = button.tag; // recover the row
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0];
// apply your logic for indexpath as in didselect row
}
While dealing with multiple sections and multiple rows it this might help you
in cell for row method
yourcell.tag=indexPath.section;
yourcell.contentview.tag=indexPath.row;
and your button action might look like this
-(void)myCellbuttonAction:(id)sender
{
UIButton *button = (UIButton *)sender; // first, cast the sender to UIButton
id rowid =[button superview];
id sectionid = [rwoid superview];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[rowid tag] inSection:[sectionid tag]];
// apply your logic for indexpath as in didselect row
}
Upvotes: 1
Reputation: 21536
A few things here.
a) I would not use an instance variable (_postCell) in your cellForRowAtIndex method. You will likely have cell re-use problems and this may well be the source of your error. Replace it with a local variable:
postcell *cell = (postCell *)[self.tableView dequeueReusableCellWithIdentifier:@"postCell"];
You will also need to replace all references to _postCell
with cell
.
b) Note that in the same line your cast uses lowercase = (postCell *)...
- I have done the same above, but it is best practice for class names to start with capital letters.
c) You have a property named nameLabel
, which suggests its a UILabel
, but you are using the setTitle:forState:
method, which implies it's a UIButton
. I would rename this property since debugging will be a lot easier if the names match the classes (or at least don't imply the wrong class).
d) When you call the addTarget:action:forControlEvents
method, your selector is for personProfile:tableView:
. The signature for that method is for an NSIndexPath and a UITableView. But your button will not be sending those arguments of those types. It will send details of the sender - i.e. the button which triggered the action. So you need to revise your method to accept arguments of that type:
[cell.nameLabel addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
e) When the method gets called, you need a way to determine which cell the sending button was on. Ideally you would subclass UIButton to add some link to the cell, but (if you have only one section) you might get away with putting the row number as a tag. To do this add:
cell.nameLabel.tag = indexPath.row;
to your cellForRowAtIndexPath:
. Then you can implement a different method to handle the button press, as follows:
-(void)buttonPressed:(id)sender {
UIButton *button = (UIButton *)sender; // first, cast the sender to UIButton
NSInteger row = button.tag; // recover the row
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:0]; // derive the indexPath, assuming section is 0
[self.tableView selectRowAtIndexPath:indexPath animated:YES]; // select the relevant row in the table (assuming the table is self.tableView)
[self performSegueWithIdentifier:@"personProfile" sender:self]; // perform the segue
}
f) Note in the above that you should not call tableView:didSelectRowAtIndexPath:
. This is for the tableView to call when the user selects the row, not for selecting rows programmatically. Use selectRowAtIndexPath:animated:
instead.
Upvotes: 1