Answers:
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 var。从情节提要中的按钮,我将@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)")
}
class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, OptionButtonsDelegate
//错误:“ MyTableViewController”与协议“ UITableViewDataSource”的冗余符合性
这应该有帮助:-
UITableViewCell* cell = (UITableViewCell*)[sender superview];
NSIndexPath* indexPath = [myTableView indexPathForCell:cell];
这里的sender是发送事件的UIButton实例。 myTableView是您正在处理的UITableView实例。
只需正确获取单元格引用,即可完成所有工作。
您可能需要从单元格的contentView中删除按钮,并将其直接添加到UITableViewCell实例的子视图中。
要么
您可以在cell.contentView中为不同的UIButton制定标签命名方案。使用此标签,以后您可以根据需要了解行和节信息。
以下代码可能会对您有所帮助。
我已将UITableView
自定义原型单元格类命名为UITableViewCell
inside 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);
}
}
注意:在这里,我已经全部UIControls
使用了Storyboard。
希望可以帮助您... !!!
我之所以喜欢下面的技术,是因为它也可以帮助我识别表的部分。
在单元格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];
事件addTask:
-(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中使用超级视图获取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)
FunctionName:已连接 //例如
当然,由于您正在使用它,因此您需要设置该按钮的标签。
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!
}
并且不要忘记在Interface Builder中设置按钮的类并将其链接到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];
}
// 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
}
如果要使用闭包将参数值从单元格传递到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
}
}
@Mani答案很好,但是单元格contentView内的视图标签通常用于其他目的。您可以改用cell的标签(或cell的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];
MyVC.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];
}