自定义UITableViewCellbutton操作?

我一直在四处寻找解决scheme,但似乎无法find一个适合我的工作。 我有一个自定义的单元格,里面有一个button。 我的问题是如何将indexPath传递给动作方法?

现在我正在做

[cell.showRewards addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside]; 

在我的cellForRowAtIndexPath方法和我的方法是:

 -(IBAction)myAction:(id)sender{ NSIndexPath *indexPath = [self.tableView indexPathForCell:(MyCustomCell *)[sender superview]]; NSLog(@"Selected row is: %d",indexPath.row); } 

有小费吗? 谢谢。

虽然我觉得设置tag的button是一种方式去。 您可能需要编写代码以确保每次单元格被重用时,相应的标签都会更新button对象。

相反,我有一种感觉,这可能工作。 尝试这个 –

 -(IBAction)myAction:(id)sender { CGPoint location = [sender locationInView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location]; UITableViewCell *swipeCell = [self.tableView cellForRowAtIndexPath:indexPath]; NSLog(@"Selected row: %d", indexPath.row); //...... } 

基本上你正在做的是获得点击发生在你的tableView的坐标。 得到坐标后, tableView可以通过使用方法indexPathForRowAtPoint:给你indexPathForRowAtPoint: 。 你很好,去追求这个…

瞧,你不只是indexPath ,还有发生点击的实际单元格。 要从你的数据源(假设它的NSArray)得到实际的数据,你可以做 –

[datasource objectAtIndex:[indexPath row]];

只是想添加我认为是所有的最好的解决scheme:在UIView类别。

这很简单:

 - (void)somethingHappened:(id)sender { NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender parentCell]]; // Your code here... } 

只需在UIView上使用这个类别:

 @interface UIView (ParentCell) - (UITableViewCell *)parentCell; @end @implementation UIView (ParentCell) - (UITableViewCell *)parentCell { UIView *superview = self.superview; while( superview != nil ) { if( [superview isKindOfClass:[UITableViewCell class]] ) return (UITableViewCell *)superview; superview = superview.superview; } return nil; } @end 
 cell.showRewards.tag = indexPath.row; 

 -(IBAction)myAction:(id)sender { UIButton *btn = (UIButton *)sender; int indexrow = btn.tag; NSLog(@"Selected row is: %d",indexrow); } 

试试这个。

 cell.showRewards.tag=indextPath.row 

在cellforrowatindexpath tableview的方法中实现这个。

 -(IBAction)myAction:(id)sender{ UIButton* btn=(UIButton*)sender; NSLog(@"Selected row is: %d",btn.tag); } 

你设置button标签值= indexpath,并检查它的function,如果标签值是这样做你想要的

您可以将索引path分配给button标记,并像您一样访问您的方法

 cell.showRewards.tag = indexPath.row; -(IBAction)myAction:(id)sender { NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender tag]]; NSLog(@"Selected row is: %d",indexPath.row); } 

在自定义的UITableViewCell类中:

 [self.contentView addSubview:but_you]; 

cellForRowAtIndexPath方法中,你可以写:

 [cell.showRewards addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside]; cell.showRewards.tag = indexPath.row; 

我觉得难以置信的是,没有真正的解决scheme。

无论出于何种原因,我发现标记方法和“在屏幕上使用单元格的视觉位置来标识正确的模型对象”在其他答案中概述有点肮脏。

这里有两个不同的方法来解决这个问题:

inheritanceUITableViewCell

我去的解决scheme是子类UITableViewCell

 @interface MyCustomCell : UITableViewCell @property (nonatomic, strong) Model *myModelObject; @end 

cellForRowAtIndexPath:创build单元格时cellForRowAtIndexPath:您可能正在使用模型对象来填充单元格数据。 在这种方法中,您可以将模型对象分配给单元格。

然后在button的点击处理程序中:

 MatchTile *cell = (MatchTile *) sender.superview.superview; if (cell && cell.myModelObject) { //Use cell.myModelObject } 

说实话,我对这个解决scheme并不满意。 将域对象附加到这样一个专门的UIKit组件感觉就像是不好的做法。

使用Objective-C关联对象

如果您不想为单元格子类化,则可以使用另外一些技巧将模型对象与单元格相关联,并稍后进行检索。

要从单元格中检索模型对象,您将需要一个唯一的键来标识它。 定义一个这样的:

 static char* OBJECT_KEY = "uniqueRetrievalKey"; 

当您使用模型对象来填充单元格时, cellForRowAtIndexPath:下行添加到您的cellForRowAtIndexPath:方法。 这将使您的模型对象与单元格对象相关联。

 objc_setAssociatedObject(cell, OBJECT_KEY, myModelObject, OBJC_ASSOCIATION_RETAIN); 

然后在任何地方你有一个单元格的引用,你可以检索模型对象使用:

 MyModelObject *myModelObject = (MyModelObject *) objc_getAssociatedObject(cell, OBJECT_KEY); 

在反思中,虽然我select了第一个(因为我已经将子类化了),但第二个解决scheme可能有点清洁,因为它仍然是ViewController的职责,用于附加和检索模型对象。 UITableViewCell不需要知道任何事情。

[sender superview]查看[sender superview]你访问不MyCustomCell ,但它是contentView 。 阅读UITableViewCell类参考:

contentView返回单元格对象的内容视图。 (只读)

 @property(nonatomic, readonly, retain) UIView *contentView 

讨论: UITableViewCell对象的内容视图是单元格显示内容的默认超级视图。 如果要通过简单地添加其他视图来自定义单元格,则应将其添加到内容视图中,以便在单元格进入和退出编辑模式时适当地定位它们。

修改代码的最简单的方法是使用[[sender superview] superview] 。 但是如果稍后在另一个视图中修改单元格并插入button,这将停止工作。 contentView出现在iPhoneOS 2.0 。 类似的未来修改会影响你的代码。 这就是为什么我不build议使用这种方式。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法写下面的代码:

  [cell.zoomButton addTarget:self action:@selector(navigateAction:) forControlEvents:UIControlEventTouchUpInside]; cell.zoomButton.tag=indexPath.row; 

然后写一个像这样的方法:

 -(IBAction)navigateAction:(id)sender { UIButton *btn = (UIButton *)sender; int indexrow = btn.tag; NSLog(@"Selected row is: %d",indexrow); currentBook = [[bookListParser bookListArray] objectAtIndex:indexrow]; KitapDetayViewController *kitapDetayViewController; if(IS_IPHONE_5) { kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:@"KitapDetayViewController" bundle:Nil]; } else { kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:@"KitapDetayViewController_iPhone4" bundle:Nil]; } kitapDetayViewController.detailImageUrl = currentBook.detailImageUrl; kitapDetayViewController.bookAuthor = currentBook.bookAuthor; kitapDetayViewController.bookName = currentBook.bookName; kitapDetayViewController.bookDescription = currentBook.bookDescription; kitapDetayViewController.bookNarrator=currentBook.bookNarrator; kitapDetayViewController.bookOrderHistory=currentBook.bookOrderDate; int byte=[currentBook.bookSizeAtByte intValue]; int mb=byte/(1024*1024); NSString *mbString = [NSString stringWithFormat:@"%d", mb]; kitapDetayViewController.bookSize=mbString; kitapDetayViewController.bookOrderPrice=currentBook.priceAsText; kitapDetayViewController.bookDuration=currentBook.bookDuration; kitapDetayViewController.chapterNameListArray=self.chapterNameListArray; // [[bookListParser bookListArray ]release]; [self.navigationController pushViewController:kitapDetayViewController animated:YES]; } 

如果你想要的button的indexPath 检测UITableView中按下哪个UIButton描述如何。

基本上button的动作变成:

  - (void)checkButtonTapped:(id)sender { CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition]; if (indexPath != nil) { ... } } 

这是“最简单的方法”来做(testingIOS11):

 NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint [[[sender superview] superview] center]];