【Objective-C】UITableViewCellに入れたUISwitchから親セルを参照

【Xcode5.1.1 + iOS 7.1 + MacOX10.9.4】

UITableViewCellをカスタマイズして、UISwitchを入れてみた。これはそんなに難しくない。こんな感じで。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    
    // cellを選択不可にする
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    // UISwitchを作成
    UISwitch *sw = [[UISwitch alloc] initWithFrame:CGRectZero];
    
    // UISwitchのタップ動作を指定
    [sw addTarget:self action:@selector(tapSwich:) forControlEvents:UIControlEventTouchUpInside];
    
    // UISwitchをaccessoryViewに代入
    cell.accessoryView = sw;
    
    cell.textLabel.text = sw_name;
    
    return cell;
}

【参考】
[XCODE] UITableViewCellに、様々なコントロール要素をのせて表示する方法 – YoheiM.NET
UITableViewCell の accessoryView を使うと少し楽 (フェンリル | デベロッパーズブログ)

で、UISwitchをタップしたときに呼ばれるtapSwichで「何番目のセルか?」(indexPath.row)を取得しようとしてハマった。
最初は「UITableViewCellに入れたんだから、その親でしょ?」とこんな感じに書いたけど取得できず。

    UITableViewCell *cell = (UITableViewCell *)[sw superview];
    int row = (int)[self.tableView indexPathForCell:cell].row;

そこで階層を調べるために、こんなふうに書いてみた。

    NSObject *t = (UITableViewCell *)[sw superview];
    NSObject *tt = (UITableViewCell *)[[sw superview] superview];
    NSObject *ttt = (UITableViewCell *)[[[sw superview] superview] superview];
    NSObject *tttt = (UITableViewCell *)[[[[sw superview] superview] superview] superview];
    
    NSLog(@"--switch  >> %@ , \n%@ , \n%@, \n%@",t,tt,ttt,tttt);

その出力結果がコレ(見やすいように一部省略)

2014-09-02 01:50:00.953 iconFaceCam[3017:60b] --switch  >> 
<UITableViewCellScrollView: ...> , 
<UITableViewCell: ...> , 
<UITableViewWrapperView: ...>, 
<UITableView: ...>

UISwitchとUITableViewCellの間に、UITableViewCellScrollViewというのが入ってるらしい。
そこで、こんな感じに書いて参照出来ました。

-(void)tapSwich:(id)sender
{
    UISwitch *sw = (UISwitch *)sender;
    
    UITableViewCell *cell = (UITableViewCell *)[[sw superview] superview];
    int row = (int)[self.tableView indexPathForCell:cell].row;
    
    // UISwitch:初期値を指定
    switch (row) {
        case 0:
            .....;            
            break;
        case 1:
            .....
            break;
        case 2:
            break;
            
        default:
            break;
    }
}

調べてみたら、この階層はiOS7になって変更されているらしいので、iOS6ではまた違うらしい。
詳しくは以下のリンクへ。

iOS7 では UITableViewCell の subviews階層が変更されている | objc-Lovers