سؤال

لدي UITableView مع 5 UITableViewCells.كل خلية تحتوي على UIButton والتي تم إعدادها على النحو التالي:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [button setTag:1];
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell viewWithTag:1];
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

سؤالي هو:في buttonPressedAction: طريقة, كيف اعرف الزر الذي تم الضغط عليه.لقد فكرت في استخدام الكلمات ولكن أنا متأكد من أن هذا هو أفضل طريق.أود أن تكون قادرة على نحو ما الوسم indexPath على السيطرة.

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    // how do I know which button sent this message?
    // processing button press for this row requires an indexPath. 
}

ما هي طريقة قياسية من فعل هذا ؟

تحرير:

لقد حلها عن طريق القيام بما يلي.أنا لا تزال ترغب في أن يكون لها رأي في ما إذا كان هذا هو طريقة قياسية من يفعل ذلك أم أن هناك طريقة أفضل ؟

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell.contentView.subviews objectAtIndex:0];
     [button setTag:indexPath.row];
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    int row = button.tag;
}

ما هو مهم أن نلاحظ أنه لا يمكن تعيين الوسم في خلق الخلية منذ الخلية قد يكون dequeued بدلا من ذلك.فإنه يشعر قذرة جدا.يجب أن يكون هناك طريقة أفضل.

هل كانت مفيدة؟

المحلول

في أبل ملحق عينة يتم استخدام الأسلوب التالي:

[button addTarget:self action:@selector(checkButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

ثم في اتصال معالج اتصال وتنسيق استرداد مسار مؤشر يحسب من أن تنسيق:

- (void)checkButtonTapped:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    if (indexPath != nil)
    {
     ...
    }
}

نصائح أخرى

لقد وجدت طريقة استخدام متطور هو متطور للحصول على مرجع إلى خلية indexPath عملت تماما.شكرا iphonedevbook.com (macnsmith) لهذه المعلومة وصلة النص

-(void)buttonPressed:(id)sender {
 UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
 NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...

}

هنا هو كيف نفعل ذلك.بسيط ومختصر:

- (IBAction)buttonTappedAction:(id)sender
{
    CGPoint buttonPosition = [sender convertPoint:CGPointZero
                                           toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
    ...
}

وجدت حل جميل لهذه المشكلة في مكان آخر, لا تعبث مع العلامات على زر:

- (void)buttonPressedAction:(id)sender {

    NSSet *touches = [event allTouches];
    UITouch *touch = [touches anyObject];
    CGPoint currentTouchPosition = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];

    // do stuff with the indexPath...
}

ماذا عن إرسال المعلومات مثل NSIndexPath في UIButton استخدام وقت التشغيل الحقن.

1) تحتاج وقت على استيراد

2) إضافة ثابت ثابت

3) إضافة NSIndexPath إلى الزر الخاص بك في وقت التشغيل باستخدام:

(الفراغ)setMetaData:(id)الهدف withObject:(id)newObj

4) اضغط على زر الحصول على البيانات الوصفية باستخدام:

(id)البيانات الوصفية:(id)الهدف

الاستمتاع

    #import <objc/runtime.h>
    static char const * const kMetaDic = "kMetaDic";


    #pragma mark - Getters / Setters

- (id)metaData:(id)target {
    return objc_getAssociatedObject(target, kMetaDic);
}

- (void)setMetaData:(id)target withObject:(id)newObj {
    objc_setAssociatedObject(target, kMetaDic, newObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}



    #On the cell constructor
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    ....
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    ....
    [btnSocial addTarget:self
                                   action:@selector(openComments:)
                         forControlEvents:UIControlEventTouchUpInside];

    #add the indexpath here or another object
    [self setMetaData:btnSocial withObject:indexPath];

    ....
    }



    #The action after button been press:

    - (IBAction)openComments:(UIButton*)sender{

        NSIndexPath *indexPath = [self metaData:sender];
        NSLog(@"indexPath: %d", indexPath.row);

        //Reuse your indexpath Now
    }

أن تفعل (@فلاديمير)'s إجابة سريعة:

var buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
var indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)!

على الرغم من أن التحقق indexPath != nil يعطيني الاصبع..."NSIndexPath هو نوع فرعي من NSString"

func buttonAction(sender:UIButton!)
    {
        var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tablevw)
        let indexPath = self.tablevw.indexPathForRowAtPoint(position)
        let cell: TableViewCell = tablevw.cellForRowAtIndexPath(indexPath!) as TableViewCell
        println(indexPath?.row)
        println("Button tapped")
    }

أود أن استخدام الوسم الملكية كما قلت وضع العلامة مثل ذلك:

[button setTag:indexPath.row];

ثم الحصول على العلامة داخل buttonPressedAction مثل ذلك:

((UIButton *)sender).tag

أو

UIButton *button = (UIButton *)sender; 
button.tag;

على الرغم من أنني مثل العلامة طريقة...إذا كنت لا تريد استخدام العلامات لأي سبب من الأسباب ، يمكنك إنشاء الأعضاء NSArray ولم يضف من الأزرار:

NSArray* buttons ;

ثم خلق تلك الأزرار قبل التقديم tableView ودفعهم إلى الصفيف.

ثم داخل tableView:cellForRowAtIndexPath: وظيفة يمكنك القيام به:

UIButton* button = [buttons objectAtIndex:[indexPath row] ] ;
[cell.contentView addSubview:button];

ثم في buttonPressedAction: وظيفة يمكنك القيام به

- (void)buttonPressedAction:(id)sender {
   UIButton* button = (UIButton*)sender ;
   int row = [buttons indexOfObject:button] ;
   // Do magic
}

للتعامل مع أقسام - أنا تخزين NSIndexPath في العرف UITableViewCell

في CLKIndexPricesHEADERTableViewCell.xib

في IB إضافة UIButton إلى XIB - لا إضافة العمل!

إضافة منفذ @الملكية (الاحتفاظ nonatomic) IBOutlet UIButton *buttonIndexSectionClose;

لا CTRL+سحب العمل في البكالوريا(يتم ذلك في التعليمات البرمجية أدناه)

@interface CLKIndexPricesHEADERTableViewCell : UITableViewCell
...
@property (retain, nonatomic) IBOutlet UIButton *buttonIndexSectionClose;
@property (nonatomic, retain) NSIndexPath * indexPathForCell;
@end

في viewForHeaderInSection (وينبغي أيضا العمل على cellForRow....الخ إذا كنت الجدول فقط 1 القسم)

- viewForHeaderInSection is called for each section 1...2...3
- get the cell CLKIndexPricesHEADERTableViewCell 
- getTableRowHEADER just does the normal dequeueReusableCellWithIdentifier
- STORE the indexPath IN the UITableView cell
- indexPath.section = (NSInteger)section
- indexPath.row = 0 always (we are only interested in sections)

- (UIView *) tableView:(UITableView *)tableView1 viewForHeaderInSection:(NSInteger)section {


    //Standard method for getting a UITableViewCell
    CLKIndexPricesHEADERTableViewCell * cellHEADER = [self getTableRowHEADER];

...استخدام القسم للحصول على البيانات الخاصة بك الخلية

...وملئه في

   indexName        = ffaIndex.routeCode;
   indexPrice       = ffaIndex.indexValue;

   //

   [cellHEADER.buttonIndexSectionClose addTarget:self
                                          action:@selector(buttonDELETEINDEXPressedAction:forEvent:)
                                forControlEvents:UIControlEventTouchUpInside];


   cellHEADER.indexPathForCell = [NSIndexPath indexPathForRow:0 inSection:section];


    return cellHEADER;
}

يضغط المستخدم على زر حذف على قسم رأس هذه المكالمات

- (void)buttonDELETEINDEXPressedAction:(id)sender forEvent:(UIEvent *)event
{
    NSLog(@"%s", __PRETTY_FUNCTION__);


    UIView *  parent1 = [sender superview];   // UiTableViewCellContentView
    //UIView *myContentView = (UIView *)parent1;

    UIView *  parent2 = [parent1 superview];  // custom cell containing the content view
    //UIView *  parent3 = [parent2 superview];  // UITableView containing the cell
    //UIView *  parent4 = [parent3 superview];  // UIView containing the table


    if([parent2 isMemberOfClass:[CLKIndexPricesHEADERTableViewCell class]]){
        CLKIndexPricesHEADERTableViewCell *myTableCell = (CLKIndexPricesHEADERTableViewCell *)parent2;

        //UITableView *myTable = (UITableView *)parent3;
        //UIView *mainView = (UIView *)parent4;

        NSLog(@"%s indexPath.section,row[%d,%d]", __PRETTY_FUNCTION__, myTableCell.indexPathForCell.section,myTableCell.indexPathForCell.row);

        NSString *key = [self.sortedKeysArray objectAtIndex:myTableCell.indexPathForCell.section];
        if(key){
            NSLog(@"%s DELETE object at key:%@", __PRETTY_FUNCTION__,key);
            self.keyForSectionIndexToDelete = key;
            self.sectionIndexToDelete = myTableCell.indexPathForCell.section;

            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Remove Index"
                                                                message:@"Are you sure"
                                                               delegate:self
                                                      cancelButtonTitle:@"No"
                                                      otherButtonTitles:@"Yes", nil];
            alertView.tag = kALERTVIEW_REMOVE_ONE_INDEX;
            [alertView show];
            [alertView release];
            //------
        }else{
            NSLog(@"ERROR: [%s] key is nil for section:%d", __PRETTY_FUNCTION__,myTableCell.indexPathForCell.section);
        }

    }else{
        NSLog(@"ERROR: [%s] CLKIndexPricesHEADERTableViewCell not found", __PRETTY_FUNCTION__);
    }
}

في هذا المثال أضفت زر حذف لذلك يجب أن تظهر UIAlertView للتأكد من ذلك

أنا مخزن القسم المفتاح في القاموس تخزين معلومات عن القسم في ايفار في VC

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
   if(alertView.tag == kALERTVIEW_REMOVE_ONE_INDEX){
        if(buttonIndex==0){
            //NO
            NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
            //do nothing
        }
        else if(buttonIndex==1){
            //YES
            NSLog(@"[%s] BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
            if(self.keyForSectionIndexToDelete != nil){

                //Remove the section by key
                [self.indexPricesDictionary removeObjectForKey:self.keyForSectionIndexToDelete];

                //sort the keys so sections appear alphabetically/numbericsearch (minus the one we just removed)
                [self updateTheSortedKeysArray];                

                //Delete the section from the table using animation
                [self.tableView beginUpdates];

                [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:self.sectionIndexToDelete]
                              withRowAnimation:UITableViewRowAnimationAutomatic];
                [self.tableView endUpdates];

                //required to trigger refresh of myTableCell.indexPathForCell else old values in UITableViewCells
                [self.tableView reloadData];
            }else{
                NSLog(@"ERROR: [%s] OBJECT is nil", __PRETTY_FUNCTION__);
            }
        }
        else {
            NSLog(@"ERROR: [%s] UNHANDLED BUTTON:%d", __PRETTY_FUNCTION__,buttonIndex);
        }
    }else {
        NSLog(@"ERROR: [%s] unhandled ALERTVIEW TAG:%d", __PRETTY_FUNCTION__,alertView.tag);
    }
}
A better way would be to subclass your button and add a indexPath property to it.

//Implement a subclass for UIButton.

@interface NewButton:UIButton
@property(nonatomic, strong) NSIndexPath *indexPath;


Make your button of type NewButton in the XIB or in the code whereever you are initializing them.

Then in the cellForRowAtIndexPath put the following line of code.

button.indexPath = indexPath;

return cell; //As usual



Now in your IBAction

-(IBAction)buttonClicked:(id)sender{
   NewButton *button = (NewButton *)sender;

//Now access the indexPath by buttons property..

   NSIndexPath *indexPath = button.indexPath; //:)
}

مع سويفت و دائرة الرقابة الداخلية 4.2 12, يمكنك اختيار واحد 5 التالية أمثلة كاملة من أجل حل مشكلتك.


#1.باستخدام UIView's convert(_:to:) و UITableView's indexPathForRow(at:)

import UIKit

private class CustomCell: UITableViewCell {

    let button = UIButton(type: .system)

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        button.setTitle("Tap", for: .normal)
        contentView.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
        button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        cell.button.addTarget(self, action: #selector(customCellButtonTapped), for: .touchUpInside)
        return cell
    }

    @objc func customCellButtonTapped(_ sender: UIButton) {
        let point = sender.convert(CGPoint.zero, to: tableView)
        guard let indexPath = tableView.indexPathForRow(at: point) else { return }
        print(indexPath)
    }

}

#2.باستخدام UIView's convert(_:to:) و UITableView's indexPathForRow(at:) (البديل)

هذا هو بديل المثال السابق حيث تمر nil إلى target المعلمة في addTarget(_:action:for:).بهذه الطريقة, إذا كان المستجيب الأول لا ينفذ العمل ، سيتم إرسال المقبل المستجيب في سلسلة الرد حتى حتى التنفيذ السليم وجدت.

import UIKit

private class CustomCell: UITableViewCell {

    let button = UIButton(type: .system)

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        button.setTitle("Tap", for: .normal)
        button.addTarget(nil, action: #selector(TableViewController.customCellButtonTapped), for: .touchUpInside)
        contentView.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
        button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        return cell
    }

    @objc func customCellButtonTapped(_ sender: UIButton) {
        let point = sender.convert(CGPoint.zero, to: tableView)
        guard let indexPath = tableView.indexPathForRow(at: point) else { return }
        print(indexPath)
    }

}

#3.باستخدام UITableView's indexPath(for:) وتفويض نمط

في هذا المثال وضعنا تحكم عرض مندوبا من الخلية.عندما الخلية زر استغلالها ، فإنه يتسبب في الدعوة إلى الطريقة المناسبة المندوب.

import UIKit

protocol CustomCellDelegate: AnyObject {
    func customCellButtonTapped(_ customCell: CustomCell)
}

class CustomCell: UITableViewCell {

    let button = UIButton(type: .system)
    weak var delegate: CustomCellDelegate?

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        button.setTitle("Tap", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        contentView.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
        button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    @objc func buttonTapped(sender: UIButton) {
        delegate?.customCellButtonTapped(self)
    }

}
import UIKit

class TableViewController: UITableViewController, CustomCellDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        cell.delegate = self
        return cell
    }

    // MARK: - CustomCellDelegate

    func customCellButtonTapped(_ customCell: CustomCell) {
        guard let indexPath = tableView.indexPath(for: customCell) else { return }
        print(indexPath)
    }

}

#4.باستخدام UITableView's indexPath(for:) و إغلاق وفد

هذا هو بديل المثال السابق حيث نستخدم الإغلاق بدلا من بروتوكول-مندوب الإعلان للتعامل مع الحنفية زر.

import UIKit

class CustomCell: UITableViewCell {

    let button = UIButton(type: .system)
    var buttontappedClosure: ((CustomCell) -> Void)?

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        button.setTitle("Tap", for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        contentView.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
        button.topAnchor.constraint(equalToSystemSpacingBelow: contentView.topAnchor, multiplier: 1).isActive = true
        button.leadingAnchor.constraint(greaterThanOrEqualToSystemSpacingAfter: contentView.leadingAnchor, multiplier: 1).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    @objc func buttonTapped(sender: UIButton) {
        buttontappedClosure?(self)
    }

}
import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        cell.buttontappedClosure = { [weak tableView] cell in
            guard let indexPath = tableView?.indexPath(for: cell) else { return }
            print(indexPath)
        }
        return cell
    }

}

#5.باستخدام UITableViewCell's accessoryType و UITableViewDelegate's tableView(_:accessoryButtonTappedForRowWith:)

إذا كان الزر الخاص بك هو UITableViewCell's الملحقات القياسية السيطرة ، أي اضغط عليه سوف يؤدي استدعاء UITableViewDelegate's tableView(_:accessoryButtonTappedForRowWith:), يسمح لك للحصول على مؤشر ذات المسار.

import UIKit

private class CustomCell: UITableViewCell {

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        accessoryType = .detailButton
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
import UIKit

class TableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(CustomCell.self, forCellReuseIdentifier: "CustomCell")
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
        return cell
    }

    override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
        print(indexPath)
    }

}

بالنسبة لي كان يعمل aswell شكرا @Cocoanut

لقد وجدت طريقة استخدام متطور هو متطور للحصول على مرجع إلى خلية indexPath عملت تماما.شكرا iphonedevbook.com (macnsmith) لهذه المعلومة وصلة النص

-(void)buttonPressed:(id)sender {
 UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
 NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];
...

}

يمكنك استخدام الوسم نمط:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     NSString *identifier = @"identifier";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
     if (cell == nil) {
         cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
         [cell autorelelase];

         UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10, 5, 40, 20)];
         [button addTarget:self action:@selector(buttonPressedAction:) forControlEvents:UIControlEventTouchUpInside];
         [button setTag:[indexPath row]]; //use the row as the current tag
         [cell.contentView addSubview:button];

         [button release];
     }

     UIButton *button = (UIButton *)[cell viewWithTag:[indexPath row]]; //use [indexPath row]
     [button setTitle:@"Edit" forState:UIControlStateNormal];

     return cell;
}

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    //button.tag has the row number (you can convert it to indexPath)
}

أنا في عداد المفقودين شيئا ؟ لا يمكنك فقط استخدام المرسل إلى تحديد زر.المرسل سوف تعطيك معلومات من هذا القبيل:

<UIButton: 0x4b95c10; frame = (246 26; 30 30); opaque = NO; tag = 104; layer = <CALayer: 0x4b95be0>>

ثم إذا كنت ترغب في تغيير خصائص زر أقول صورة الخلفية تخبر المرسل:

[sender setBackgroundImage:[UIImage imageNamed:@"new-image.png"] forState:UIControlStateNormal];

إذا كنت في حاجة إلى الوسم ثم ACBurk طريقة ما يرام.

// how do I know which button sent this message?
// processing button press for this row requires an indexPath.

واضحة جدا في الواقع:

- (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;
    CGPoint rowButtonCenterInTableView = [[rowButton superview] convertPoint:rowButton.center toView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rowButtonCenterInTableView];
    MyTableViewItem *rowItem = [self.itemsArray objectAtIndex:indexPath.row];
    // Now you're good to go.. do what the intention of the button is, but with
    // the context of the "row item" that the button belongs to
    [self performFooWithItem:rowItem];
}

يعمل بشكل جيد بالنسبة لي :P

إذا كنت ترغب في ضبط الهدف الخاص بك-عمل الإعداد ، يمكنك تضمين المعلمة الحدث في الأسلوب ، ومن ثم استخدام لمسات من هذا الحدث لحل إحداثيات تعمل باللمس.الإحداثيات لا تزال بحاجة إلى حل في المس عرض الحدود ، ولكن هذا قد يبدو من الأسهل بالنسبة لبعض الناس.

إنشاء nsmutable مجموعة ووضع كل زر في ذلك مجموعة من قسم رعاية مصالح الولايات المتحدة[مجموعة addObject:yourButton];

في اضغط على زر طريقة

-

 (void)buttonPressedAction:(id)sender
{
    UIButton *button = (UIButton *)sender;

for(int i=0;i<[yourArray count];i++){

if([buton isEqual:[yourArray objectAtIndex:i]]){

//here write wat u need to do

}
}

اختلاف طفيف على Cocoanuts الجواب (الذي ساعدني في حل هذه) عندما كان زر في تذييل جدول (الذي يمنعك من العثور على 'بالنقر فوق الخلية':

-(IBAction) buttonAction:(id)sender;
{
    id parent1 = [sender superview];   // UiTableViewCellContentView
    id parent2 = [parent1 superview];  // custom cell containing the content view
    id parent3 = [parent2 superview];  // UITableView containing the cell
    id parent4 = [parent3 superview];  // UIView containing the table

    UIView *myContentView = (UIView *)parent1;
    UITableViewCell *myTableCell = (UITableViewCell *)parent2;
    UITableView *myTable = (UITableView *)parent3;
    UIView *mainView = (UIView *)parent4;

    CGRect footerViewRect = myTableCell.frame;
    CGRect rect3 = [myTable convertRect:footerViewRect toView:mainView];    

    [cc doSomethingOnScreenAtY:rect3.origin.y];
}

أنا دائما استخدام العلامات.

تحتاج إلى فئة فرعية UITableviewCell والتعامل مع الصحافة زر من هناك.

انها بسيطة ؛ جعل العرف خلية تأخذ مخرج زر

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
         NSString *identifier = @"identifier";
        customCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];

    cell.yourButton.tag = indexPath.Row;

- (void)buttonPressedAction:(id)sender

تغيير معرف في الأسلوب أعلاه إلى (UIButton *)

يمكنك الحصول على قيمة هذا الزر الذي يتم استغلالها عن طريق القيام المرسل.الوسم.

فرعية الزر لتخزين القيمة المطلوبة ، ربما إنشاء بروتوكول (ControlWithData أو شيء).تعيين قيمة عند إضافة الزر إلى عرض الجدول الخلية.في اتصال ومتابعة الحدث ، انظر إذا كان المرسل يطيع البروتوكول واستخراج البيانات.أنا عادة تخزين مرجع إلى كائن الفعلية التي يتم تقديمها على الطاولة عرض الخلية.

سويفت 2 التحديث

هنا كيفية معرفة ما الذي تم استغلالها على زر + إرسال البيانات إلى آخر ViewController من هذا الزر indexPath.row كما أفترض أن هذا هو الهدف بالنسبة لمعظم!

@IBAction func yourButton(sender: AnyObject) {


     var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
        let indexPath = self.tableView.indexPathForRowAtPoint(position)
        let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
        UITableViewCell
        print(indexPath?.row)
        print("Tap tap tap tap")

    }

بالنسبة لأولئك الذين يستخدمون ViewController الدرجة وأضاف tableView, أنا باستخدام ViewController بدلا من TableViewController لذا يدويا إضافة tableView من أجل الوصول إلى ذلك.

هنا هو رمز لتمرير البيانات إلى آخر VC عند النقر على هذا الزر و اجتياز الخلية indexPath.row

@IBAction func moreInfo(sender: AnyObject) {

    let yourOtherVC = self.storyboard!.instantiateViewControllerWithIdentifier("yourOtherVC") as! YourOtherVCVIewController



    var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let indexPath = self.tableView.indexPathForRowAtPoint(position)
    let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
    UITableViewCell
    print(indexPath?.row)
    print("Button tapped")


    yourOtherVC.yourVarName = [self.otherVCVariable[indexPath!.row]]

    self.presentViewController(yourNewVC, animated: true, completion: nil)

}

نلاحظ هنا أنا باستخدام مخصص الخلية هذه الشفرة يعمل تماما بالنسبة لي

 @IBAction func call(sender: UIButton)
    {
        var contentView = sender.superview;
        var cell = contentView?.superview as EmployeeListCustomCell
        if (!(cell.isKindOfClass(EmployeeListCustomCell)))
        {
            cell = (contentView?.superview)?.superview as EmployeeListCustomCell
        }

        let phone = cell.lblDescriptionText.text!
        //let phone = detailObject!.mobile!
        let url:NSURL = NSURL(string:"tel://"+phone)!;
        UIApplication.sharedApplication().openURL(url);
    }

كريس Schwerdt هو الحل ولكن بعد ذلك في سويفت عملت بالنسبة لي:

@IBAction func rateButtonTapped(sender: UIButton) {
    let buttonPosition : CGPoint = sender.convertPoint(CGPointZero, toView: self.ratingTableView)
    let indexPath : NSIndexPath = self.ratingTableView.indexPathForRowAtPoint(buttonPosition)!

    print(sender.tag)
    print(indexPath.row)
}

هذه المشكلة إلى قسمين:

1) الحصول على مؤشر مسار UITableViewCell الذي يحتوي على الضغط UIButton

هناك بعض الاقتراحات مثل:

  • تحديث UIButton's tag في cellForRowAtIndexPath: طريقة استخدام مؤشر مسار row القيمة.هذا ليس حل جيد كما أنه يتطلب تحديث tag باستمرار أنها لا تعمل مع الجدول وجهات النظر مع أكثر من قسم واحد.

  • إضافة NSIndexPath خاصية مخصصة الخلية وتحديث بدلا من UIButton's tag في cellForRowAtIndexPath: الأسلوب.هذا يحل متعددة القسم المشكلة ولكن لا تزال ليست جيدة كما أنه يتطلب تحديث دائما.

  • حفظ ضعف refence إلى الوالدين UITableView في العرف الخليوي أثناء إنشاء و استخدام indexPathForCell: طريقة الحصول على مؤشر المسار.يبدو أفضل قليلا, لا تحتاج إلى تحديث أي شيء في cellForRowAtIndexPath: طريقة ولكن لا يزال يتطلب وضع ضعيف المرجع عند العرف الخلية التي تم إنشاؤها.

  • باستخدام الخلية superView الخاصية للحصول على إشارة إلى الوالدين UITableView.لا تحتاج إلى إضافة أي خصائص مخصصة الخلية لا تحتاج إلى تعيين/تحديث أي شيء على الخلق/في وقت لاحق.ولكن الخلية superView يعتمد على دائرة الرقابة الداخلية تفاصيل التنفيذ.لذلك لا يمكن استخدامها مباشرة.

ولكن هذا لا يمكن أن يتحقق باستخدام حلقة بسيطة ، ونحن على يقين الخلية في السؤال قد يكون في UITableView:

UIView* view = self;
while (view && ![view isKindOfClass:UITableView.class])
    view = view.superview;
UITableView* parentTableView = (UITableView*)view;

إذن هذه الاقتراحات يمكن دمجها في مجموعة بسيطة وآمنة الخليوي مخصصة طريقة للحصول على مؤشر المسار:

- (NSIndexPath *)indexPath
{
    UIView* view = self;

    while (view && ![view isKindOfClass:UITableView.class])
        view = view.superview;

    return [(UITableView*)view indexPathForCell:self];
}

من الآن فصاعدا, هذه الطريقة يمكن أن تستخدم للكشف عن UIButton هو الضغط عليه.

2) إبلاغ الأطراف الأخرى عن زر اضغط الحدث

بعد داخليا معرفة UIButton هو الضغط الذي الخليوي مخصصة مع الدقيق مؤشر مسار هذه المعلومات تحتاج إلى إرسالها إلى الأطراف الأخرى (على الأرجح وجهة النظر تحكم التعامل مع UITableView).لذا هذا الزر انقر فوق الحدث يمكن التعامل معها بنفس التجريد والمنطق مستوى didSelectRowAtIndexPath: طريقة UITableView مندوب.

نهجين يمكن استخدام هذا:

أ) التفويض: الخليوي مخصصة يمكن أن يكون delegate الملكية و يمكن تعريف البروتوكول.عندما يتم الضغط على زر فقط يقوم هو مندوب الطرق على انها delegate مكان الإقامة.ولكن هذا delegate العقار يحتاج إلى أن يتم تعيين لكل مخصص الخلية عندما يتم إنشاؤها.كبديل ، الخليوي مخصصة يمكن أن تختار القيام به مندوب طرق على الوالدين عرض الجدول هذا delegate أيضا.

ب) مركز إعلام: مخصص الخلايا يمكن تعريف مخصص الإخطار اسم و وظيفة هذا الإعلام مع مؤشر مسار الوالد عرض جدول المعلومات المقدمة في userInfo الكائن.لا حاجة لوضع أي شيء لكل خلية فقط إضافة مراقب مخصصة خلية الإعلام بما فيه الكفاية.

يمكنني استخدام الحل الذي فرعية UIButton واعتقدت أن مجرد مشاركتها هنا رموز في "سويفت":

class ButtonWithIndexPath : UIButton {
    var indexPath:IndexPath?
}

ثم تذكر لتحديث انها indexPath في cellForRow(at:)

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let returnCell = tableView.dequeueReusableCell(withIdentifier: "cellWithButton", for: indexPath) as! cellWithButton
    ...
    returnCell.button.indexPath = IndexPath
    returnCell.button.addTarget(self, action:#selector(cellButtonPressed(_:)), for: .touchUpInside)

    return returnCell
}

حتى عند الرد على زر الحدث يمكنك استخدامه مثل

func cellButtonPressed(_ sender:UIButton) {
    if sender is ButtonWithIndexPath {
        let button = sender as! ButtonWithIndexPath
        print(button.indexPath)
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top