テーブルビューと、テーブルセルテンプレート用の別のペン先を持つView Controllerがあります。セルテンプレートにはいくつかのボタンがあります。 Tableビューを定義したビューコントローラ内でクリックされたセルのインデックスと共にボタンclickにアクセスしたいです。
それで、私はUITableView
とViewController.h
、ViewController.m
とTableTemplate.h
を持っているTableTemplate.m
とTableTemplate.xib
を持っています。 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になります。それを回避するために、参加者を設定します。 (そうすることで再利用可能なセルクラスを作成することになります。基本クラスと同じセルクラスを使用することができ、あなたがしなければならないのはデリゲートメソッドを実装することだけです。)
まず、セルがボタンのクリックを伝達(委任)するために使用されるインターフェイス(プロトコル)が必要です。 (プロトコル用に別の.hファイルを作成して、Table View Controllerとカスタムセルクラスの両方に含めることができます。[ORそれをカスタムセルクラスに追加するだけです。 Table View Controllerでは)
@protocol CellDelegate <NSObject>
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data;
@end
このプロトコルをカスタムセルおよびTable View Controllerに含めます。また、Table View Controllerがこのプロトコルを確認していることを確認してください。
カスタムセルに2つのプロパティを作成します。
@property (weak, nonatomic) id<CellDelegate>delegate;
@property (assign, nonatomic) NSInteger cellIndex;
UIButton
IBActionデリゲートをクリックします。(View Controllerに委任する必要があるカスタムセルクラス内のすべてのアクションについても同様です)。
- (IBAction)buttonClicked:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(didClickOnCellAtIndex:withData:)]) {
[self.delegate didClickOnCellAtIndex:_cellIndex withData:@"any other cell data/property"];
}
}
セルをデキューした後のTable View Controller cellForRowAtIndexPath
で、上記のプロパティを設定します。
cell.delegate = self;
cell.cellIndex = indexPath.row; // Set indexpath if its a grouped table.
そしてTable View Controllerでデリゲートを実装します。
- (void)didClickOnCellAtIndex:(NSInteger)cellIndex withData:(id)data
{
// Do additional actions as required.
NSLog(@"Cell at Index: %d clicked.\n Data received : %@", cellIndex, data);
}
これは、Table View Controllerでカスタムセルボタンアクションを取得するための理想的な方法です。
タグで遊ぶ代わりに、私は異なるアプローチを取りました。私のサブクラスのUITableViewCell(OptionButtonsCell)にデリゲートを作成し、indexPath変数を追加しました。ストーリーボードのボタンから@IBActionをOptionButtonsCellに接続し、そこで適切なindexPathを持つデリゲートメソッドを興味のある人に送信します。インデックスパスのセルに、現在のindexPathを設定して動作します。
コードがそれ自身のために話すようにしましょう:
Swift 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);
}
}
注:ここではストーリーボードを使ってすべてのUIControls
を取得しました。
それがあなたを助けることができることを願っています... !!!
それはまた私がテーブルのセクションを識別するのに役立ちますので、私は技術の下に私が好きな理由。
セルcellForRowAtIndexPathにButtonを追加します。
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;
}
}
この助けを願っています。
UITableViewCell構造体が変更され、代わりに "UITableViewCellScrollView"を取得するようになったため、TarunのコードはiOS 7では機能しません。
この記事 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)
FunctionName:connected //例えば
そしてもちろん、あなたはそれを使っているので、あなたはそのボタンのタグを設定する必要があります。
myButton.tag = indexPath.row
これを達成するには、UITableViewCellをサブクラス化します。インターフェイスビルダーでそれを使用し、そのセルにボタンをドロップし、アウトレットを介してそれを接続すればそこに行く。
Connected関数でタグを取得するには
func connected(sender: UIButton) {
let buttonTag = sender.tag
// Do any additional setup
}
クロージャ付きSwift
Niceソリューションは、カスタム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()
}
}
View Controllerの場合: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
つまり、これらのコードをTable View Controllerに追加するだけです。
@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.
}
}
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
}
}
その仕事.
- (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
}
swift 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];
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];
}