LoginSignup
38
38

More than 5 years have passed since last update.

iOS7でUITableViewCell上のボタンをタップしたら落ちた

Last updated at Posted at 2013-10-27

こんなエラーが起きた

大分略していますがこんな感じのコードを書いて、UITableViewCell上のボタンをタップした時の処理を実行してたのですが、

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  //~ 略 ~
  cell = [[RensouCell alloc]
             initWithStyle:UITableViewCellStyleDefault
           reuseIdentifier:CellIdentifier];

  // ボタンタップ時のイベント感知
  [cell.likeButton addTarget:self
                      action:@selector(onClickLikeButton:)
            forControlEvents:UIControlEventTouchUpInside];
  //~ 略 ~
}

// ボタンタップ時に実行される処理
- (void)onClickLikeButton:(UIButton *)button
{
  // タップされたボタンから、対応するセルを取得する
  RensouCell *cell = (RensouCell *)[button superview];
  //~ 略 ~
  [cell likeRensou];
}

iOS7で実行してみたら、こんなエラーを出して落ちてしまいました。(iOS6以前だと普通に動く)

[UITableViewCellScrollView likeRensou]: unrecognized selector sent to instance 0x9b453e0

「UITableViewCellScrollView に、likeRensou なんてメソッド無いよ!」というエラーなのですが、そもそもUITableViewCellScrolView ってどこから出てきたんだよ…、という感じでした。(;´Д`)

原因

ぐぐったら以下の記事で解説されていました。
参考:iOS7 では UITableViewCell の subviews階層が変更されている | objc-Lovers

なるほど階層が変わったんですね。確かにこれだと、タップされたUIButtonのsuperviewを取得すると、UITableViewCellScrollViewになりますわ…。

追記

twitterで指摘されて気づいたのですが、UITableViewCellにUIButtonを配置する際は、selfにaddSubviewするんじゃなくて、self.contentViewに対してaddSubviewするのが正しいようです…orz
参考:ynumerator_blog: Custome UITableViewCellの[self addSubview]と[self.contentView addView]の違い

正しいやり方でやっていると、UIButtonのsuperviewはUITableViewCellContentになります。この辺のviewの構造については、以下の図が分かりやすいです。
参考:iOS6とiOS7のUITableViewCell構造の違い

解決策

調べていくうちに、今までやっていたsuperviewを使って対応するUITableViewCellを取得するやり方は、元々推奨されていないという事が分かったので、ガラッと方法を変えてUIEventを使うようにしました。これでばっちり!!

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  //~ 略 ~
  cell = [[RensouCell alloc]
             initWithStyle:UITableViewCellStyleDefault
           reuseIdentifier:CellIdentifier];

  // ボタンタップ時のイベント感知
  [cell.likeButton addTarget:self
                      action:@selector(onClickLikeButton:event:)
            forControlEvents:UIControlEventTouchUpInside];
  //~ 略 ~
}

// ボタンタップ時に実行される処理
- (void)onClickLikeButton:(UIButton *)button event:(UIEvent *)event
{
  // タップされたボタンから、対応するセルを取得する
  NSIndexPath *indexPath = [self indexPathForControlEvent:event];
  RensouCell *cell = (RensouCell *)[self.tableView cellForRowAtIndexPath:indexPath];
  //~ 略 ~
  [cell likeRensou];
}

// UIControlEventからタッチ位置のindexPathを取得する
- (NSIndexPath *)indexPathForControlEvent:(UIEvent *)event {
    UITouch *touch = [[event allTouches] anyObject];
    CGPoint p = [touch locationInView:self.tableView];
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
    return indexPath;
}

参考:Objective-C:UITableViewCell上に配置したButtonのタップを感知する方法 - Qiita [キータ]

解決策その2

上で挙げたような修正が大変な場合は、オススメは出来ませんが、以下のような修正方法もあるらしいです。一応紹介。

参考:既存アプリのiOS 7対応 | iOS 7エンジニア勉強会

というわけで

無事修正したものを再申請できました!!早く審査通らないかな(´ω`)

38
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
38