例えばUITableViewCellのaccessoryViewにUISwitchを付けたとします。
UISwitch* sw = [UISwitch new];
sw.on = b;
[sw addTarget:self action:@selector(changeSwitch:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = sw;
//スイッチおした時
- (void)changeSwitch:(UISwitch*)sender{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell*)[[(UISwitch*)sender superview] superview]];
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
}
さて、このような実装をすると何の問題があるかというと、テーブルのセルをタップしてもdidSelectRowAtIndexPath:は呼ばれるため、UISwitchがオフになっているのに内容はオンになったりして整合性が取れなくなります。
そのためUISwitchだけを反応するようにする必要があります。
ここでセルにuserinteractionプロパティを使うのはハズレです。
userinterctionはsubviewにも反映されるのでUISwitchもろとも動かなくなります。
hitTest:を使うのもハズレです。
ではどうするかというと、
-(NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
を利用します。
-(NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell*cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if ([[cell.accessoryView class] isSubclassOfClass:[UISwitch class]]) {
return nil;
}
return indexPath;
}
このように実装すればタップ後のdidselectは呼ばれず、UISwitchからの直接呼び出しのみが有効になります。