5

我已经尝试了这里发布的几种方法,但是我无法让我的表充满开关来返回已更改开关的单元格的索引值。我正在以编程方式创建包含表的视图(没有 xib)。

TableSandboxAppDelegate.m我用以下方法实例化视图控制器didFinishLaunchingWithOptions:

...
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);

我的日志结果始终是“Switch changed at index: 0”。我觉得问题出在 CGPoint 行中,我尝试了“sender”([sender superview]、[[sender superview]superview] 等)的替换组合。我不觉得那条线指向显示表格的视图。

我究竟做错了什么?

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

4

6 回答 6

11

标签是一个不错的解决方案,但有点笨拙,因为单元格 - 以及它们的子视图 - 不断被重用,改变它们的行 - 因此它们需要的标签。

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

- (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
}
于 2013-10-09T03:30:53.483 回答
6

您可以将切换视图标签设置为行索引。代替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;
    ...
}

添加此帮助函数以替换viewWithTag:调用

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);
    ...
 }
于 2013-10-09T03:16:06.177 回答
1

如果您使用基于块的东西(例如https://github.com/brightsoftdev/iOS-Block-Based-Bindings/blob/master/UISwitch%2BBindings.m),则无需担心获取行,因为您可以在块中引用传递给 tableView:cellForRowAtIndexPath: 的 indexPath。

于 2013-10-10T01:10:15.407 回答
0

您可以创建 UISwitch 的子类并添加 indexPath 属性,然后只需在 cellForRowAtIndexPath 中设置 indexPath:

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

    return returnCell;
}
于 2013-10-10T16:40:29.897 回答
0

与@danh 类似,我使用我多次使用的扩展提出了这个解决方案。

@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
于 2013-10-10T00:35:05.397 回答
0

对于 iOS6+,你可以维护一个 NSMutableArrayqueuedSwitches

如果不是空的,-tableView:cellForrowAtIndexPath:您将进行一个开关并将其放在自定义单元格上并将其分配给一个属性。如果为空,则创建一个新的。

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

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

开关都连接到一个动作。

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

    //…
}
于 2013-10-10T01:24:04.267 回答