6

我有一个表视图控制器,其中包含多个 UISwitch 控件。我将委托设置为表视图控制器,对所有开关具有相同的操作。我需要能够确定更改了哪个开关,因此我创建了一个字符串数组,其中包含每个开关的名称。数组中的索引将放在每个 UISwitch 的 tag 属性中。

但是,我已准备好将 tag 属性用于其他用途,即使用 viewWithTag 在 cellForRowAtIndexPath 的单元格中找到正确的控件!(我需要在每个单元格中设置几件事。)

那么,我在这里的想法是否正确?我觉得我在如何确切地找出哪个 UISwitch 改变了它的值方面相当有限,所以我可以用它做一些有用的事情。

4

4 回答 4

5

我通过像这样子类化 UISwitch 来解决这个问题:

@interface NamedUISwitch : UISwitch {
NSString *name;

}

它看起来很优雅(不需要索引数组)并且标签属性可以随意做任何事情。

我读到你必须小心在 Objective-C 中进行子类化,但是......

于 2010-04-01T21:49:13.027 回答
1

我已经编写了一个 UISwitch 子类,它带有一个基于块的处理程序,用于值更改控制事件,这可以在尝试跟踪哪个开关的值已更改时提供帮助。理想情况下,我们可以用组合而不是子类化做类似的事情,但这很适合我的需要。

https://gist.github.com/3958325

你可以像这样使用它:

ZUISwitch *mySwitch = [ZUISwitch alloc] init];

[mySwitch onValueChange:^(UISwitch *uiSwitch) {
        if (uiSwitch.on) {
            // do something
        } else {
            // do something else
        }
    }];

您也可以从 XIB 文件中使用它,方法是将开关拖到您的视图上,然后将其类更改为 ZUISwitch

于 2012-10-26T11:56:34.607 回答
0

你的方法很接近。我在类似情况下所做的是创建单独的 UITableViewCell 子类,将 UISwitch 的标记设置为索引路径的 index.row,并且仅在表视图的特定部分中使用该 UITableViewCell 子类。这允许您使用单元格的标签来唯一地确定哪个单元格具有事件,而无需维护单独的索引列表(就像您正在做的那样)。

因为单元格类型是唯一的,所以您可以通过在 UITableViewCell 子类上创建方法/属性来轻松访问单元格的其他元素。

例如:

@interface TableViewToggleCell : UITableViewCell {
    IBOutlet UILabel *toggleNameLabel;
    IBOutlet UILabel *detailedTextLabel;
    IBOutlet UISwitch *toggle;
    NSNumber *value;
    id owner;
}

@property (nonatomic, retain) UILabel *toggleNameLabel;
@property (nonatomic, retain) UILabel *detailedTextLabel;
@property (nonatomic, retain) UISwitch *toggle;
@property (nonatomic, retain) id owner;

-(void) setLable:(NSString*)aString;
-(void) setValue:(NSNumber*)aNum;
-(NSNumber*)value;
-(void) setTagOnToggle:(NSInteger)aTag;

-(IBAction)toggleValue:(id)sender;

@end

在:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // ... prior iniitalization code for creating cell is assumed
toggleCell.owner = self;
[toggleCell setLable:@"some string value"];
[toggleCell setTagOnToggle:indexPath.row];
toggleCell.owner = self;
return toggleCell;
   //...  handle cell set up for other cell types as needed
}

所有者是单元的代表,然后可用于在控制器中启动操作。确保将 UISwitch 连接到 toggleValue 操作,以便在 UISwitch 更改状态时可以在委托中启动操作:

-(IBAction)toggleValue:(id)sender;
{
    BOOL oldValue = [value boolValue];
    [value release];
    value = [[NSNumber numberWithBool:!oldValue] retain];
    [owner performSelector:@selector(someAction:) withObject:toggle];
}

通过使用方法调用传递 UISwitch,您可以访问单元格的索引路径。您还可以通过显式使用 ivar 来存储单元格的 NSIndexPath 并使用方法调用传递整个单元格来绕过 tag 属性的使用。

于 2010-04-01T12:52:47.560 回答
0

我意识到我迟到了大约三年,但我已经开发了一个没有子类化的解决方案,我认为它更可取(并且更简单)。我正在使用与 Thaurin 描述的场景完全相同的场景。

- (void)toggleSwitch:(id) sender
{
    // declare the switch by its type based on the sender element
    UISwitch *switchIsPressed = (UISwitch *)sender;
    // get the indexPath of the cell containing the switch
    NSIndexPath *indexPath = [self indexPathForCellContainingView:switchIsPressed];
    // look up the value of the item that is referenced by the switch - this
    // is from my datasource for the table view
    NSString *elementId = [dataSourceArray objectAtIndex:indexPath.row];
}

然后你要声明上面显示的方法,indexPathForCellContainingView。这似乎是一种不必要的方法,因为乍一看,您所要做的就是识别 switch 的 superview,但是 ios7 和早期版本的 superview 之间存在差异,所以这可以处理所有问题:

- (NSIndexPath *)indexPathForCellContainingView:(UIView *)view {
    while (view != nil) {
        if ([view isKindOfClass:[UITableViewCell class]]) {
            return [self.myTableView indexPathForCell:(UITableViewCell *)view];
        } else {
            view = [view superview];
        }
    }   
    return nil;
}
于 2013-12-29T07:54:38.037 回答