[英]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.