自定义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]];