如何检索UISwitch的UITableView行号?

我已经尝试了几种方法张贴在这里,但我不能让我的表充满开关返回改变的开关的单元格的索引值。 我正在以编程方式创build包含表的视图(没有xib)。

TableSandboxAppDelegate.m我在didFinishLaunchingWithOptions:实例化视图控制器didFinishLaunchingWithOptions: with:

 ... TableSandboxViewController *sandboxViewController = [[TableSandboxViewController alloc] init]; [[self window] setRootViewController:sandboxViewController]; ... 

TableViewController.h文件读取:

 @interface TableSandboxViewController : UITableViewController { NSMutableArray *_questionOrder; NSMutableArray *switchStates; } @end 

TableViewController.m cellForRowAtIndexPath:读取:

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MainCell"]; UISwitch *theSwitch = nil; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MainCell"]; theSwitch = [[UISwitch alloc] initWithFrame:CGRectZero]; theSwitch.tag = 100; [theSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; [cell.contentView addSubview:theSwitch]; } else { theSwitch = [cell.contentView viewWithTag:100]; } if ([[switchStates objectAtIndex:indexPath.row] isEqualToString:@"ON"]) { theSwitch.on = YES; } else { theSwitch.on = NO; } return cell; 

TableViewController.m -(IBAction)switchChanged:(UISwitch *)sender读取:

 UITableViewCell *theParentCell = [[sender superview] superview]; NSIndexPath *indexPathOfSwitch = [self.tableView indexPathForCell:theParentCell]; NSLog(@"Switch changed at index: %d", indexPathOfSwitch.row); 

我的日志结果始终是“索引切换:0”。 我觉得问题是在CGPoint行,我已经尝试了“sender”([sender superview],[[sender superview] superview]等replace组合)。 我不觉得这条线是指向显示表的视图。

我究竟做错了什么?

注意10/9,9:15 EDT:我的目标是能够处理大约100个是/否的问题,所以重用是一个关键。 我想滚动并让表格成为每个开关的状态,并且能够在离开视图时检索它们。

标签是一个好的解决scheme,但有点笨拙,因为单元格(因此它们的子视图)不断被重复使用,改变它们的行,因此也是他们需要的标签。

相反,我通常保留其中的一个:

 - (NSIndexPath *)indexPathWithSubview:(UIView *)subview { while (![subview isKindOfClass:[UITableViewCell self]] && subview) { subview = subview.superview; } return [self.tableView indexPathForCell:(UITableViewCell *)subview]; } 

那么当我得到一个IBAction:

 - (IBAction)someSubviewAction:(id)sender { NSIndexPath *indexPath = [self indexPathWithSubview:(UIView *)sender]; // carry on from here } 

您可以将切换视图标记设置为行索引。 而不是theSwitch.tag = 100;

 -(UITableViewCell*)tableView:table cellForRowAtIndexPath:indexPth { UISwitch *theSwitch = nil; if (cell == nil) { ... // as per your example [cell.contentView addSubview:theSwitch]; } else { theSwitch = subviewWithClass(cell.contentView, [UISwitch class]); } theSwitch.tag = indexPath.row; ... } 

添加这个辅助函数来replaceviewWithTag: call

 UIView *subviewWithClass(UIView *contentview, Class klass) { for (UIView *view in contentview.subviews) if ([view isKindOfClass:klass]) return view; return nil; } 

然后在你的switchChanged函数中检索标签,这是一个行索引

 -(IBAction)switchChanged:(UISwitch *)sender { NSLog(@"Selected Switch - %d", sender.tag); ... } 

如果你使用基于块的(如https://github.com/brightsoftdev/iOS-Block-Based-Bindings/blob/master/UISwitch%2BBindings.m ),你不需要担心获得行,因为您可以引用传入tableView:cellForRowAtIndexPath:的块中的indexPath。

和@danh类似,我使用了多次使用的扩展来提出这个解决scheme。

 @interface UIView (Find) - (id)findSuperviewOfClass:(Class)class; - (NSIndexPath *)findIndexPath; @end @implementation UIView (Find) - (id)findSuperviewOfClass:(Class)class { return [self isKindOfClass:class] ? self : [self.superview findSuperviewOfClass:class]; } - (NSIndexPath *)findIndexPath { UITableView *tableView = [self findSuperviewOfClass:[UITableView class]]; return [tableView indexPathForCell:[self findSuperviewOfClass:[UITableViewCell class]]]; } @end 

对于iOS6 +,您可以维护一个NSMutableArray queuedSwitches

-tableView:cellForrowAtIndexPath:如果不是空的,你将会得到一个开关,并把它放在自定义单元格中,并将它分配给一个属性。 如果为空,则创build一个新的。

-tableView:didEndDisplayingCell:forRowAtIndexPath:你将它添加到quededSwitches并将其从它的单元格中删除。

这将只为可见单元分配足够的开关并重新使用它们。

开关全部接线到一个动作。

 -(void)switchAction:(UISwitch *)switch { NSIndexPath *indexPath = [self.tableView indexPathForCell:[switch superView]]; //… } 

你可以创build一个UISwitch的子类并添加一个indexPath属性,然后在cellForRowAtIndexPath中设置indexPath:

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { SwitchCell *returnCell = [tableView dequeueReusableCellWithIdentifier:@"SwitchCell" forIndexPath:indexPath]; returnCell.switch.indexPath = indexPath; return returnCell; }