2012-05-29 99 views
15

處理自定義UITableViewCell按鈕的按鈕觸摸事件的最佳做法是什麼?Objective c - 處理自定義UITableViewCell按鈕的按鈕觸摸事件的最佳做法

我的課: MyViewControllerMyCustomCell

我能想到的三個選項:

第一選項 -有按鈕的MyCustomCell的屬性,然後在MyViewController添加一個目標吧.m文件以MyViewController作爲目標。

MyViewController .m文件

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"customCell"; 

    MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
    cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

    [cell.theButton addTarget:self 
         action:@selector(theButtonTapped:) 
      forControlEvents:UIControlEventTouchUpInside]; 
    } 

    // Configure the cell...  
    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

- (void)theButtonTapped:(UIButton *)sender 
{ 
    MyCustomCell *selectedCell = (MyCustomCell *)sender.superview; 

    if (selectedCell) { 
     NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell]; 
     MyModel *selectedModel = [self.model objectAtIndex:indexPath.row]; 

     // do something with the model... 
    } 
} 

第二選項 -如果自定義單元格在IB做,將筆尖文件的所有者是MyViewController,在MyViewController實施buttonTapped:方法和連接按鈕的觸摸的內心事件到buttonTapped:方法。

第三選項 -如果自定義單元格並沒有在IB做,在MyCustomCell .m文件添加一個目標按鈕與MyCustomCell爲目標。
定義MyCustomCellDelegate@property (nonatomic, assign) id<MyCustomCellDelegate> delegate添加到MyCustomCell,並在點擊按鈕時調用此代理。
設置MyViewController作爲單元的委託時創建單元格和實現MyCustomCellDelegate協議。

MyCustomCell .h文件中

@class MyCustomCell; 

@protocol MyCustomCellDelegate <NSObject> 
- (void)buttonTappedOnCell:(MyCustomCell *)cell; 
@end 

@interface MyCustomCell : UITableViewCell 

@property (nonatomic, retain) UIButton *theButton; 
@property (nonatomic, assign) id<MyCustomCellDelegate> delegate; 

@end 

MyCustomCell .m文件

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{ 
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
    if (self) { 
     // Initialization code 
     self.theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     self.theButton.frame = CGRectMake(10,10,50,30); 
     [self addSubview:self.theButton]; 

     [self.theButton addTarget:self 
          action:@selector(theButtonTapped:) 
       forControlEvents:UIControlEventTouchUpInside]; 
    } 
    return self; 
} 

- (void)theButtonTapped:(UIButton *)sender 
{ 
    [self.delegate buttonTappedOnCell:self]; 
} 

MyViewController .m文件

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"customCell"; 

    MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 

     cell.delegate = self; 
    } 

    // Configure the cell...  
    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

- (void)buttonTappedOnCell:(MyCustomCell *)selectedCell 
{ 
    if (selectedCell) { 
     NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell]; 
     MyModel *selectedModel = [self.model objectAtIndex:indexPath.row]; 

     // do something with the model... 
    } 
} 
+1

我會去的選項1似乎最可讀的我。我使用了類似的方法,但是我在自定義單元格中設置了委託並處理自定義單元格中的按鈕,然後通過檢查委託是否在那裏調用視圖控制器中的函數。 –

回答

11

存儲單元格的行作爲tag您的自定義按鈕的特性。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // bla bla bla 
    if (!cell) 
    { 
     //bla bla bla 
     [cell.yourButton addTarget:self selector:@selector(yourButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 
    } 
    // bla bla bla 
    cell.yourButton.tag = indexPath.row; 
} 

-(void)yourButtonTapped:(id)sender 
{ 
    int tag = [(UIButton *)sender tag]; 
    NSLog(@"tapped button in cell at row %i", tag); 
} 
+0

這樣做有沒有好處,而不是我做了什麼? MyCustomCell * selectedCell =(MyCustomCell *)sender.superview; – Eyal

+0

我上次檢查時,自定義單元格中的按鈕將單元格的內容視圖視爲超級視圖。 – Kreiri

+0

該按鈕應該添加到contentView,其超視圖是單元格。 – hwaxxer

1

從我的角度來看,使用標記會破壞代碼的嚴謹性。另外,當你有多個部分時,使用標籤肯定會讓你的代碼變得混亂。

爲了避免這個問題,你可以繼承UITableViewCell,並讓它擁有一個indexPath屬性讓單元知道它的精確位置。

這裏的另一個問題是,如果UITableView調用API來insertdelete行,你必須更新可見單元格的位置數據

我不認爲這是最好的做法。

還有一種更好的方法。


我強烈建議,當你必須處理在你的細胞不同的觸摸事件使用MVVM。

在此模式下,您的自定義UITableViewCell將保留自定義CellViewModel。這個類將負責保存與單元關聯的所有數據,因此您可以檢索數據並將事件處理邏輯放入單元中。

0

我已經通過繼承的UIButton實現了基於塊的方法:

typedef void (^ActionBlock)(id sender); 

@interface UIBlockButton : UIButton { 
    ActionBlock _actionBlock; 
} 

-(void)handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action; 
​@end 

@implementation UIBlockButton 

-(void) handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action 
    { 
     _actionBlock = action; 
     [self addTarget:self action:@selector(callActionBlock:) forControlEvents:event]; 
     } 

    -(void) callActionBlock:(id)sender{ 
    _actionBlock(sender); 
    } 

@end 

而在tableview中代表:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    if (!cell) 
    { 
    cell.yourButton.tag = indexPath.row;// pass tag 
    [cell.yourButton handleControlEvent:UIControlEventTouchUpInside withBlock:^(id sender) { 
    // your selector action code 
    NSLog(@"tapped button in cell at row %i",[(UIButton *)sender tag]); 
    }]; 
    } 
} 
0

在某些時候,你的按鈕被挖掘,在這一點上它是一個子視圖一個是某個tableview子視圖的單元格。

只要編寫一個方法,需要一個視圖,沿着superview鏈找到包含的單元格,進一步查找tableview,然後向tableview索引單元格的indexPath。

這比存儲包含一行的標記要容易得多,也更可靠,因爲在編輯tableview時不會遇到問題,並且在需要時可以找到它所需的indexPath indexPath,而不是在一些完全不相關的代碼中創建單元格時。

0

雨燕3.0解決方案

cell.btnRequest.tag = indexPath.row 

cell.btnRequest.addTarget(self,action:#selector(buttonClicked(sender:)), for: .touchUpInside) 

func buttonClicked(sender:UIButton) { 

    let buttonRow = sender.tag 
}