لدي وحدة تحكم عرض مع عرض جدول وبنك الاستثمار القومي منفصلة لقالب خلية الجدول. يحتوي قالب الخلية على بعض الأزرار. أرغب في الوصول إلى زر النقر مع فهرس الخلية التي تم النقر فوقها داخل وحدة تحكم العرض حيث قمت بتحديد طريقة عرض الجدول.
لذلك لدي ViewController.h
و ViewController.m
حيث لدي UITableView
و 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 منفصل للبروتوكول وتضمينه في كل من وحدة التحكم في عرض الجدول وفئات الخلايا المخصصة OR فقط قم بإضافته في فئة الخلية المخصصة والتي سيتم تضمينها على أي حال في وحدة تحكم عرض الجدول )
@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 الحالي ويعمل :)
دع الكود يتحدث عن نفسه:
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];
هنا المرسل هو مثيل UIButton الذي يرسل الحدث. myTableView هو مثيل UITableView الذي تتعامل معه.
مجرد الحصول على مرجع الخلية الصحيح ويتم كل العمل.
قد تحتاج إلى إزالة الأزرار من محتوى الخلية وعرضها وإضافتها مباشرة إلى مثيل UITableViewCell لأنها طريقة عرض فرعية.
أو
يمكنك صياغة نظام تسمية علامات ل UIButtons مختلفة في cell.contentView. باستخدام هذه العلامة ، يمكنك لاحقًا معرفة معلومات الصف والقسم حسب الحاجة.
التعليمات البرمجية التالية قد تساعدك.
لقد أخذت 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
باستخدام 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;
}
}
تأمل هذه المساعدة.
لا يعمل كود تارون على iOS7 ، لأن هيكل UITableViewCell قد تغير والآن سيحصل على "UITableViewCellScrollView" بدلاً من ذلك.
يحتوي هذا المنشور الحصول على UITableViewCell مع superview في iOS 7 على حل جيد لإنشاء حلقة للعثور على العرض الأصل الصحيح ، بغض النظر عن أي تغييرات مستقبلية في الهيكل. يتلخص في إنشاء حلقة:
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
}
سويفت 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];
}
استخدام سويفت الإغلاق:
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
}
}
// 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 الخاصة بالخلية):
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
داخل "cellForRowAtIndexPath" في MyVC.m:
//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];
}