programing

UI 테이블 보기에서 누른 UI 버튼 감지

skycolor 2023. 4. 27. 22:05
반응형

UI 테이블 보기에서 누른 UI 버튼 감지

나는 있습니다UITableView5와 함께UITableViewCells에는 각셀다음을포다니합함은▁a다▁contains가 있습니다.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;
}

: ▁the.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;
}

주의할 점은 셀이 대신 대기열에서 해제될 수 있기 때문에 셀 작성 시 태그를 설정할 수 없습니다.그것은 매우 더러운 느낌입니다.더 좋은 방법이 있을 겁니다.

Apple의 액세서리 샘플에는 다음 방법이 사용됩니다.

[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에 대한 참조를 얻기 위해 superview의 superview를 사용하는 방법이 완벽하게 작동한다는 것을 알게 되었습니다.팁 링크 텍스트에 대해 iphonedevbook.com (맥스미스)에게 감사드립니다.

-(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];
    ...
}

Swift 4.2와 iOS 12를 사용하면 문제를 해결하기 위해 다음 5가지 예제 중 하나를 선택할 수 있습니다.


# #1 사용하기 사용하기UIViewconvert(_:to:)그리고.UITableViewindexPathForRow(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 사용하기 사용하기UIViewconvert(_:to:)그리고.UITableViewindexPathForRow(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 사용하기 사용하기UITableViewindexPath(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 사용하기 사용하기UITableViewindexPath(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 사용하기 사용하기UITableViewCellaccessoryType그리고.UITableViewDelegatetableView(_:accessoryButtonTappedForRowWith:)

가 단가다경우인 UITableViewCell의 표준 액세서리 컨트롤, 탭하면 호출이 트리거됩니다.UITableViewDelegatetableView(_: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)
    }

}

다른 곳에서 이 문제에 대한 좋은 해결책을 찾았고, 버튼에 있는 태그를 만지작거리지 않았습니다.

- (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런타임 주입을 사용합니다.

가져오기에 런타임이 필요합니다.

정적 상수 추가

을 더하다NSIndexPath다음을 사용하여 실행 시 단추로 이동:

(void)setMetaData:(id)object:(id)newObj로 대상 설정

버튼에서 다음을 사용하여 메타데이터 가져오기를 누릅니다.

(id)metaData: (id)target

즐거운 시간 되세요.

    #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
    }

To Do (@Vladimir)의 대답은 Swift입니다.

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];

그런 다음 다음 다음과 같이 버튼PressedAction 안에 태그를 넣습니다.

((UIButton *)sender).tag

또는

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

술잡를좋아만지하, 어떤 하고 싶지 를 만들 수 .NSArray사전 제작된 버튼:

NSArray* buttons ;

그런 다음 표를 렌더링하기 전에 단추를 만듭니다. 보기 및 배열로 밀어넣습니다.

에 에그음안에다 에.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
}

섹션 처리 - 사용자 지정 UITableViewCell에 NSIndexPath를 저장했습니다.

CLKIndex 가격HEADERTableCell.xib 보기

INIB에서 XIB에 UI 버튼 추가 - 액션 추가 안 함!

outlet @property(유지, 비원자) IOButlet UIButton *버튼 추가인덱스 섹션 닫기;

IB에서 Ctrl+Drag를 사용하지 마십시오(아래 코드에서 수행).

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

inviewForHeaderInSection(cellForRow에 대해서도 작동해야 함...)테이블에 섹션이 하나만 있는 경우 등)

- 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;
}

사용자가 섹션 헤더에서 DELETE 버튼을 누르면 호출됩니다.

- (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__);
    }
}

이 예에서는 삭제 버튼을 추가했으므로 확인하려면 UIAertView를 표시해야 합니다.

섹션과 키를 VC의 ivar에 섹션에 대한 정보를 저장하는 사전에 저장합니다.

- (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; //:)
}

저에게도 효과가 있어요, 고마워요 @Cocanut.

셀의 indexPath에 대한 참조를 얻기 위해 superview의 superview를 사용하는 방법이 완벽하게 작동한다는 것을 알게 되었습니다.팁 링크 텍스트에 대해 iphonedevbook.com (맥스미스)에게 감사드립니다.

-(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 어레이를 만들고 [array 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

}
}

단추가 표 바닥글에 있을 때('클릭된 셀'을 찾을 수 없음) Cocanuts의 약간 변형이 응답합니다(이것은 이 문제를 해결하는 데 도움이 되었습니다).

-(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

를 위메를의 id로 합니다.(UIButton *)

sender.tag를 실행하면 어떤 버튼을 누르고 있는지 값을 얻을 수 있습니다.

버튼을 하위 분류하여 필요한 값을 저장하고 프로토콜(ControlWithData)을 만들 수 있습니다.표 보기 셀에 단추를 추가할 때 값을 설정합니다.터치업 이벤트에서 발신인이 프로토콜을 준수하고 데이터를 추출하는지 확인합니다.일반적으로 테이블 뷰 셀에 렌더링되는 실제 객체에 대한 참조를 저장합니다.

SWIFT 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를 추가한 사용자의 경우 TableViewController 대신 ViewController를 사용하고 있으므로 테이블View에 액세스하기 위해 수동으로 추가했습니다.

다음은 해당 버튼을 누르고의 데이터를 전달할 때 다른 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);
    }

Chris Schwerdt의 솔루션이지만 Swift에서는 저를 위해 작동했습니다.

@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)
}

이 문제는 두 부분으로 나뉩니다.

의인스 의 경로 UITableViewCell에는 눌린 레스내포함합다니을용된이 있습니다.UIButton

다음과 같은 몇 가지 제안이 있습니다.

  • 업데이트 중UIButtontagcellForRowAtIndexPath:의 index path를 하는 rowvalue.가 필요하기 . 업데이트가 필요하기 때문에 좋은 솔루션이 아닙니다.tag섹션이 둘 이상인 테이블 뷰에서는 연속적으로 작동하지 않습니다.

  • 추가NSIndexPath 및 사용자 지정 셀에 대한 속성UIButtontagcellForRowAtIndexPath: 여러 때문에 않습니다.이것은 여러 섹션의 문제를 해결하지만 항상 업데이트가 필요하기 때문에 여전히 좋지 않습니다.

  • UITableView하고 사용하는 정의 indexPathForCell:인덱스 경로를 가져오는 메서드입니다.더 나은 것 , 조금더나같다니습에서 . 업데이트할 필요가 없습니다.cellForRowAtIndexPath:메서드이지만 사용자 지정 셀을 만들 때 약한 참조를 설정해야 합니다.

  • 셀용을 superView를 얻는 상위항대참가올속져성를조한.UITableView사용자 지정 셀에 속성을 추가할 필요가 없으며, 작성/나중에 설정/업데이트할 필요가 없습니다.의 하만셀은지셀은.superView세부 정보에 달라집니다.iOS 구현 세부 정보에 따라 다릅니다.그래서 그것은 직접 사용할 수 없습니다.

그러나 문제의 셀이 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를 누릅니다.

버튼 누르기 이벤트에 대해 다른 사람에게 알리기

내적으로어것이느부▁which것이ally▁knowing▁intern▁after느어를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)
    }
}

언급URL : https://stackoverflow.com/questions/1802707/detecting-which-uibutton-was-pressed-in-a-uitableview

반응형