[英]Get button click inside UITableViewCell
我有一个带有表格视图的视图控制器和一个用于表格单元格模板的单独笔尖。 单元格模板有一些按钮。 我想访问按钮单击以及在我定义表视图的视图控制器内单击的单元格的索引。
所以我有ViewController.h
和ViewController.m
,我有UITableView
和TableTemplate.h
, TableTemplate.m
和TableTemplate.xib
在那里我定义了笔尖。 我想要ViewController.m
带有单元ViewController.m
引的按钮单击事件。
关于我该怎么做的任何帮助?
1) 在你的cellForRowAtIndexPath:
方法中,将按钮标签指定为索引:
cell.yourbutton.tag = indexPath.row;
2)为您的按钮添加目标和操作,如下所示:
[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
3) 在ViewControler
基于索引的代码操作如下:
-(void)yourButtonClicked:(UIButton*)sender
{
if (sender.tag == 0)
{
// Your code here
}
}
多个部分的更新:
您可以检查此链接以检测表视图中多行和部分的按钮单击。
代表是要走的路。
正如使用视图的其他答案所见,可能会过时。 谁知道明天可能会有另一个包装器并且可能需要使用cell superview]superview]superview]superview]
。 如果你使用标签,你最终会得到 n 个 if else 条件来识别单元格。 为了避免所有这些设置代表。 (通过这样做,您将创建一个可重用的单元类。您可以使用相同的单元类作为基类,您所要做的就是实现委托方法。)
首先,我们需要一个接口(协议),它将被单元用来通信(委托)按钮点击。 (您可以为协议创建一个单独的 .h 文件并包含在表格视图控制器和自定义单元格类中,或者只需将其添加到自定义单元格类中,无论如何都会包含在表格视图控制器中)
@protocol CellDelegate <NSObject>
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
@end
将此协议包含在自定义单元格和表格视图控制器中。 并确保表视图控制器确认此协议。
在自定义单元格中创建两个属性:
@property (weak, nonatomic) id<CellDelegate>delegate;
@property (assign, nonatomic) NSInteger cellIndex;
在UIButton
IBAction 委托中单击:(对于需要委托回视图控制器的自定义单元格类中的任何操作都可以这样做)
- (IBAction)buttonClicked:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) {
[self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"];
}
}
在单元格出列后,在表视图控制器cellForRowAtIndexPath
,设置上述属性。
cell.delegate = self;
cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.
并在表视图控制器中实现委托:
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data
{
// Do additional actions as required.
NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data);
}
这将是在表格视图控制器中获取自定义单元格按钮操作的理想方法。
我没有使用标签,而是采用了不同的方法。 为我的 UITableViewCell(OptionButtonsCell) 子类做了委托,并添加了一个 indexPath 变量。 从故事板中的按钮,我将@IBAction 连接到 OptionButtonsCell,然后我将带有正确 indexPath 的委托方法发送给任何感兴趣的人。 在索引路径的单元格中,我设置了当前的 indexPath 并且它有效:)
让代码不言自明:
斯威夫特 3 Xcode 8
OptionButtonsTableViewCell.swift
import UIKit
protocol OptionButtonsDelegate{
func closeFriendsTapped(at index:IndexPath)
}
class OptionButtonsTableViewCell: UITableViewCell {
var delegate:OptionButtonsDelegate!
@IBOutlet weak var closeFriendsBtn: UIButton!
var indexPath:IndexPath!
@IBAction func closeFriendsAction(_ sender: UIButton) {
self.delegate?.closeFriendsTapped(at: indexPath)
}
}
MyTableViewController.swift
class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate {...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "optionCell") as! OptionButtonsTableViewCell
cell.delegate = self
cell.indexPath = indexPath
return cell
}
func closeFriendsTapped(at index: IndexPath) {
print("button tapped at index:\(index)")
}
这应该有帮助:-
UITableViewCell* cell = (UITableViewCell*)[sender superview];
NSIndexPath* indexPath = [myTableView indexPathForCell:cell];
这里的sender是发送事件的 UIButton 实例。 myTableView是您正在处理的 UITableView 实例。
只需正确获取单元格引用即可完成所有工作。
您可能需要从单元格的 contentView 中删除按钮并将它们直接添加到 UITableViewCell 实例,因为它是子视图。
要么
您可以在 cell.contentView 中为不同的 UIButton 制定标签命名方案。 使用这个标签,以后可以根据需要知道行&节信息。
以下代码可能对您有所帮助。
我已经采取UITableView
与命名的自定义原型细胞类UITableViewCell
内UIViewController
。
所以我有ViewController.h
、 ViewController.m
和TableViewCell.h
、 TableViewCell.m
这是代码:
ViewController.h
@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
@property (strong, nonatomic) IBOutlet UITableView *tblView;
@end
ViewController.m
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return (YourNumberOfRows);
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = @"cell";
__weak TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (indexPath.row==0) {
[cell setDidTapButtonBlock:^(id sender)
{
// Your code here
}];
}
return cell;
}
自定义单元类:
TableViewCell.h
@interface TableViewCell : UITableViewCell
@property (copy, nonatomic) void (^didTapButtonBlock)(id sender);
@property (strong, nonatomic) IBOutlet UILabel *lblTitle;
@property (strong, nonatomic) IBOutlet UIButton *btnAction;
- (void)setDidTapButtonBlock:(void (^)(id sender))didTapButtonBlock;
@end
和
UITableViewCell.m
@implementation TableViewCell
- (void)awakeFromNib {
// Initialization code
[self.btnAction addTarget:self action:@selector(didTapButton:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)didTapButton:(id)sender {
if (self.didTapButtonBlock)
{
self.didTapButtonBlock(sender);
}
}
注意:这里我使用 Storyboard 获取了所有UIControls
。
希望能帮到你。。。!!!
我喜欢下面的技术的原因是因为它也帮助我识别表格的部分。
在单元格 cellForRowAtIndexPath 中添加按钮:
UIButton *selectTaskBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[selectTaskBtn setFrame:CGRectMake(15, 5, 30, 30.0)];
[selectTaskBtn setTag:indexPath.section]; //Not required but may find useful if you need only section or row (indexpath.row) as suggested by MR.Tarun
[selectTaskBtn addTarget:self action:@selector(addTask:) forControlEvents:UIControlEventTouchDown];
[cell addsubview: selectTaskBtn];
事件添加任务:
-(void)addTask:(UIButton*)btn
{
CGPoint buttonPosition = [btn convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
int currentIndex = indexPath.row;
int tableSection = indexPath.section;
}
}
希望这有帮助。
使用 Swift 闭包:
class TheCell: UITableViewCell {
var tapCallback: (() -> Void)?
@IBAction func didTap(_ sender: Any) {
tapCallback?()
}
}
extension TheController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TheCell.identifier, for: indexPath) as! TheCell {
cell.tapCallback = {
//do stuff
}
return cell
}
}
Tarun 的代码在 iOS7 上不起作用,因为 UITableViewCell 结构发生了变化,现在他会得到“UITableViewCellScrollView”。
这篇文章在 iOS 7 中使用 superview 获取 UITableViewCell有一个很好的解决方案,即创建一个循环来找到正确的父视图,而不管未来的结构发生任何变化。 它归结为创建一个循环:
UIView *superView = [sender superview];
UIView *foundSuperView = nil;
while (nil != superView && nil == foundSuperView) {
if ([superView isKindOfClass:[UITableViewCell class]]) {
foundSuperView = superView;
} else {
superView = superView.superview;
}
}
该链接具有更可重用解决方案的代码,但这应该有效。
您需要为该按钮添加目标。
myButton.addTarget(self, action: #selector(ClassName.FunctionName(_:), forControlEvents: .TouchUpInside)
函数名称:已连接// 例如
当然,您需要设置该按钮的标签,因为您正在使用它。
myButton.tag = indexPath.row
您可以通过继承 UITableViewCell 来实现这一点。 在界面生成器中使用它,在该单元格上放一个按钮,通过插座连接它,然后就可以了。
要在连接的函数中获取标签:
func connected(sender: UIButton) {
let buttonTag = sender.tag
// Do any additional setup
}
带有闭包的 Swift 3
一个不错的解决方案是在自定义 UITableViewCell 中使用闭包来回调 viewController 以进行操作。
在单元格中:
final class YourCustomCell: UITableViewCell {
var callbackClosure: (() -> Void)?
// Configure the cell here
func configure(object: Object, callbackClosure: (() -> Void)?) {
self.callbackClosure = callbackClosure
}
// MARK: - IBAction
extension YourCustomCell {
@IBAction fileprivate func actionPressed(_ sender: Any) {
guard let closure = callbackClosure else { return }
closure()
}
}
在视图控制器中:Tableview 委托
extension YourViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let cell: YourCustomCell = cell as? YourCustomCell else { return }
cell.configure(object: object, callbackClosure: { [weak self] in
self?.buttonAction()
})
}
}
fileprivate extension YourViewController {
func buttonAction() {
// do your actions here
}
}
我发现在您的单元格内对按钮进行子类化是最简单的(Swift 3):
class MyCellInfoButton: UIButton {
var indexPath: IndexPath?
}
在您的单元格类中:
class MyCell: UICollectionViewCell {
@IBOutlet weak var infoButton: MyCellInfoButton!
...
}
在表视图或集合视图的数据源中,当单元格出列时,为按钮指定其索引路径:
cell.infoButton.indexPath = indexPath
所以你可以把这些代码放到你的表视图控制器中:
@IBAction func handleTapOnCellInfoButton(_ sender: MyCellInfoButton) {
print(sender.indexPath!) // Do whatever you want with the index path!
}
并且不要忘记在您的界面生成器中设置按钮的类并将其链接到handleTapOnCellInfoButton
函数!
编辑:
使用依赖注入。 要设置调用闭包:
class MyCell: UICollectionViewCell {
var someFunction: (() -> Void)?
...
@IBAction func didTapInfoButton() {
someFunction?()
}
}
并在集合视图委托的 willDisplay 方法中注入闭包:
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
(cell as? MyCell)?.someFunction = {
print(indexPath) // Do something with the indexPath.
}
}
它为我工作。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIButton *Btn_Play = (UIButton *)[cell viewWithTag:101];
[Btn_Play addTarget:self action:@selector(ButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
-(void)ButtonClicked:(UIButton*)sender {
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.Tbl_Name];
NSIndexPath *indexPath = [self.Tbl_Name indexPathForRowAtPoint:buttonPosition];
}
如果您想使用闭包将参数值从单元格传递到 UIViewController 则
//Your Cell Class
class TheCell: UITableViewCell {
var callBackBlockWithParam: ((String) -> ()) = {_ in }
//Your Action on button
@IBAction func didTap(_ sender: Any) {
callBackBlockWithParam("Your Required Parameter like you can send button as sender or anything just change parameter type. Here I am passing string")
}
}
//Your Controller
extension TheController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TheCell.identifier, for: indexPath) as! TheCell {
cell.callBackBlockWithParam = { (passedParamter) in
//you will get string value from cell class
print(passedParamter)
}
return cell
}
}
// Add action in cell for row at index path -tableView
cell.buttonName.addTarget(self, action: #selector(ViewController.btnAction(_:)), for: .touchUpInside)
// Button Action
@objc func btnAction(_ sender: AnyObject) {
var position: CGPoint = sender.convert(.zero, to: self.tableView)
let indexPath = self.tableView.indexPathForRow(at: position)
let cell: UITableViewCell = tableView.cellForRow(at: indexPath!)! as
UITableViewCell
}
快速 4:
inside the cellForItemAt , cell.chekbx.addTarget(self, action: #selector(methodname), for: .touchUpInside) then outside of cellForItemAt @objc func methodname() { //your function code }
@Mani 的回答很好,但是单元格的 contentView 中的视图标签通常用于其他目的。 您可以使用单元格的标签(或单元格的 contentView 标签):
1) 在cellForRowAtIndexPath:
方法中,将单元格的标签指定为索引:
cell.tag = indexPath.row; // or cell.contentView.tag...
2)为您的按钮添加目标和操作,如下所示:
[cell.yourbutton addTarget:self action:@selector(yourButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
3)创建返回发件人行的方法(感谢@Stenio Ferreira):
- (NSInteger)rowOfSender:(id)sender
{
UIView *superView = sender.superview;
while (superView) {
if ([superView isKindOfClass:[UITableViewCell class]])
break;
else
superView = superView.superview;
}
return superView.tag;
}
4)基于索引的代码动作:
-(void)yourButtonClicked:(UIButton*)sender
{
NSInteger index = [self rowOfSender:sender];
// Your code here
}
CustomTableCell.h 是一个 UITableViewCell:
@property (weak, nonatomic) IBOutlet UIButton *action1Button;
@property (weak, nonatomic) IBOutlet UIButton *action2Button;
导入后的 MyVC.m:
@interface MYTapGestureRecognizer : UITapGestureRecognizer
@property (nonatomic) NSInteger dataint;
@end
在 MyVC.m 中的“cellForRowAtIndexPath”中:
//CustomTableCell
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
//Set title buttons
[cell.action1Button setTitle:[NSString stringWithString:NSLocalizedString(@"action1", nil)] forState:UIControlStateNormal];
[cell.action2Button setTitle:[NSString stringWithString:NSLocalizedString(@"action2", nil)] forState:UIControlStateNormal];
//Set visibility buttons
[cell.action1Button setHidden:FALSE];
[cell.action2Button setHidden:FALSE];
//Do 1 action
[cell.action1Button addTarget:self action:@selector(do1Action :) forControlEvents:UIControlEventTouchUpInside];
//Do 2 action
MYTapGestureRecognizer *action2Tap = [[MYTapGestureRecognizer alloc] initWithTarget:self action:@selector(do2Action :)];
cancelTap.numberOfTapsRequired = 1;
cancelTap.dataint = indexPath.row;
[cell.action2Button setUserInteractionEnabled:YES];
[cell.action2Button addGestureRecognizer:action2Tap];
我的VC.m:
-(void)do1Action :(id)sender{
//do some action that is not necessary fr data
}
-(void)do2Action :(UITapGestureRecognizer *)tapRecognizer{
MYTapGestureRecognizer *tap = (MYTapGestureRecognizer *)tapRecognizer;
numberTag = tap.dataint;
FriendRequest *fr = [_list objectAtIndex:numberTag];
//connect with a WS o do some action with fr data
//actualize list in tableView
[self.myTableView reloadData];
}
cell.show.tag=indexPath.row;
[cell.show addTarget:self action:@selector(showdata:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)showdata:(id)sender
{
UIButton *button = (UIButton *)sender;
UIStoryboard *storyBoard;
storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
SecondViewController *detailView = [storyBoard instantiateViewControllerWithIdentifier:@"SecondViewController"];
detailView.string=[NSString stringWithFormat:@"%@",[_array objectAtIndex:button.tag]];
[self presentViewController:detailView animated:YES completion:nil];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.