8

「連絡先」セルを含む「連絡先リスト」テーブルビューがあり、タップすると、その連絡先の電子メールアドレスを電子メールコンポーザに表示する必要がある電子メールボタンが含まれています。

UIButton をそのセルの「連絡先」インスタンスに関連付ける最良の方法は何ですか?

頭に浮かんだ 2 つのアプローチに対する回答を作成しましたが、満足できるものではありません。あなたはどちらを好みますか、それとももっと良いものを提案してください!

4

7 に答える 7

15

アプローチ 2:

セルにアクションを処理させ、カスタム デリゲート メソッドを呼び出します。

// YMContactCell.h
@protocol YMContactCellDelegate
- (void)contactCellEmailWasTapped:(YMContactCell*)cell;
@end

@interface YMContactCell
@property (weak, nonatomic) id<YMContactCellDelegate> delegate;
@end

// YMContactCell.m
- (IBAction)emailContact:(id)sender {
    [self.delegate contactCellEmailWasTapped:self];
}

// ContactListViewController.m
- (void)contactCellEmailWasTapped:(YMContactCell*)cell;
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    YMContact *contact = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    // present composer with `contact` ...
}

ビューでイベントを処理することは、MVC の原則に違反していませんか?

于 2013-04-01T14:30:30.870 に答える
7

私がよく目にする方法は、indexPath.row と同じタグをボタンに割り当てることです。

- (CustomCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.theLabel.text = self.theData[indexPath.row];
    cell.button.tag = indexPath.row;
    [cell.button addTarget:self action:@selector(doSomething:) forControlEvents:UIControlEventTouchUpInside];
    return cell;
}



-(void)doSomething:(UIButton *) sender {
    NSLog(@"%@",self.theData[sender.tag]);
    //sender.tag will be equal to indexPath.row
}
于 2013-04-01T17:24:50.473 に答える
4

別の解決策:

私にとって、このようなものは完璧に機能し、非常にエレガントに見えます:

- (void)buttonClicked:(id)sender
      CGPoint buttonPosition = [sender convertPoint:CGPointZero
                                       toView:self.tableView];
      NSIndexPath *clickedIP = [self.tableView indexPathForRowAtPoint:buttonPosition];

      // When necessary 
      // UITableViewCell *clickedCell = [self.tableView cellForRowAtIndexPath:clickedIP];
}

2017 年 12 月 1 日更新

しばらくして、多くの UITableViews を実装した後、ここで他の人が既に提案している委任パターンを使用することが最善の解決策であることを認める必要があります。

于 2014-03-24T14:54:04.467 に答える
3

迅速な閉鎖アプローチ

少し迅速な新しいアプローチを見つけたと思います。それについてどう思うか教えてください。

あなたの携帯:

class ButtonCell: UITableViewCell {
    var buttonAction: ( () -> Void)?
    
    func buttonPressed() {
       self.buttonAction?()
   }
}

あなたの UITableViewDataSource:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CallCell", for: indexPath)
         //Handled inside 
         cell.buttonAction = {
            //Button pressed 
         }
         //Handle in method
         cell.buttonAction = self.handleInnerCellButtonPress() 
 }

この呼び出し内でデータを渡すこともできます。セルまたはセル内に保存されているもののように。

よろしく、
アレックス

于 2016-11-22T12:11:04.270 に答える
1

アプローチ 1:

ボタンからセルのビュー階層をトラバースして、セルを決定し、そこからインデックス パスを決定します。

// ContactListViewController.m

- (IBAction)emailContact:(id)sender {
    YMContact *contact = [self contactFromContactButton:sender];
    // present composer with `contact`...
}

- (YMContact *)contactFromContactButton:(UIView *)contactButton {
    UIView *aSuperview = [contactButton superview];
    while (![aSuperview isKindOfClass:[UITableViewCell class]]) {
        aSuperview = [aSuperview superview];
    }
    YMContactCell *cell = (id) aSuperview;
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    return [[self fetchedResultsController] objectAtIndexPath:indexPath];
}

私にはぎこちなく感じます。ちょっと「まあ」…</p>

于 2013-04-01T14:29:26.413 に答える
0

別のアプローチを提供します。アクティブなターゲットを割り当てないだけで、イベントはレスポンダー チェーンを通過します。

[self.actionButton addTarget:nil action:@selector(onActionButtonClick:) forControlEvents:UIControlEventTouchUpInside];

次に、View Controllerで次のようにします。

- (void)onActorButtonClick:(id)sender {
  if ([sender isKindOfClass:UIButton.class]) {
    UITableViewCell *cell = [self findAncestorTableCell:(UIView *)sender]; //See other answer to fetch the cell instance.
    NSIndexPath *indexPath = [self.listTable indexPathForCell:cell];
    ...
  }
}

ただし、これによりコンパイラの警告が発生します。これを追加して無視します。

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
...
#pragma clang diagnostic pop
于 2015-02-06T03:45:10.520 に答える