【问题标题】:UISwitch in a UITableView cellUITableView 单元格中的 UISwitch
【发布时间】:2011-04-15 18:18:25
【问题描述】:

如何在UITableView 单元格中嵌入UISwitch?示例可以在设置菜单中看到。

我目前的解决方案:

UISwitch *mySwitch = [[[UISwitch alloc] init] autorelease];
cell.accessoryView = mySwitch;

【问题讨论】:

  • 你目前的做法有什么问题?

标签: iphone objective-c cocoa-touch uitableview uiswitch


【解决方案1】:

对于快速用户

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "TableIdentifer")
        let aswitch = UISwitch()
        cell.accessoryView = aswitch 
}

【讨论】:

  • 这段代码的工作原理是你不能使用变量名“switch”,因为它是为 Switch 语句保留的。所以使用其他任何东西都可以“aSwitch”等。
【解决方案2】:

这是一个更完整的解决方案,关闭和打开发生在视图层(UITableViewCell)上,它通过didSelectdidDeselect将事件转发给tableView委托:

class CustomCell: UITableViewCell {
    private lazy var switchControl: UISwitch = {
        let s = UISwitch()
        s.addTarget(self, action: #selector(switchValueDidChange(_:)), for: .valueChanged)
        return s
    }()

    override func awakeFromNib() {
        self.accessoryView = switchControl
        self.selectionStyle = .none // to show the selection style only on the UISwitch
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        (self.accessoryView as? UISwitch)?.isOn = selected
    }

    @objc private func switchValueDidChange(_ sender: UISwitch) { // needed to treat switch changes as if the cell was selected/unselected
        guard let tv = self.superview as? UITableView, let ip = tv.indexPath(for: self) else {
            fatalError("Unable to cast self.superview as UITableView or get indexPath")
        }
        setSelected(sender.isOn, animated: true)
        if sender.isOn {
            tv.delegate?.tableView?(tv, didSelectRowAt: ip)
        } else {
            tv.delegate?.tableView?(tv, didDeselectRowAt: ip)
        }
    }
}

在你的代表身上


func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
    return false // to disable interaction since it happens on the switch
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // to make sure it is rendered correctly when dequeuing:
    // stuff
    if isSelected { // stored value to know if the switch is on or off
        tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
    } else {
        tableView.deselectRow(at: indexPath, animated: true)
    }
    // more stuff
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // do your thing when selecting
}

func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
    // do your thing when deselecting
}

【讨论】:

    【解决方案3】:
    if (indexPath.row == 0) {//If you want UISwitch on particular row
        UISwitch *theSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
        [cell addSubview:theSwitch];
        cell.accessoryView = theSwitch;
    }
    

    【讨论】:

    • 你为什么使用initWithFrame?为什么使用addSubviewswitch 不能用作变量名。
    • 抱歉交换机名称。我有一些代码..我只是在其中更改了变量名。
    • 它对我有用。使用更少代码的有效解决方案。
    • 我只需要设置单元格的附件视图属性就可以完成这项工作。我认为没有必要将开关添加为子视图。
    【解决方案4】:

    将其设置为附件视图通常是要走的路。您可以在tableView:cellForRowAtIndexPath: 中进行设置,您可能希望在切换开关时使用目标/动作来执行某些操作。像这样:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        switch( [indexPath row] ) {
            case MY_SWITCH_CELL: {
                UITableViewCell *aCell = [tableView dequeueReusableCellWithIdentifier:@"SwitchCell"];
                if( aCell == nil ) {
                    aCell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"SwitchCell"] autorelease];
                    aCell.textLabel.text = @"I Have A Switch";
                    aCell.selectionStyle = UITableViewCellSelectionStyleNone;
                    UISwitch *switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
                    aCell.accessoryView = switchView;
                    [switchView setOn:NO animated:NO];
                    [switchView addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
                    [switchView release];
                }
                return aCell;
            }
            break;
        }
        return nil;
    }
    
    - (void)switchChanged:(id)sender {
        UISwitch *switchControl = sender;
        NSLog( @"The switch is %@", switchControl.on ? @"ON" : @"OFF" );
    }
    

    【讨论】:

    • 我认为应该是对应的单元格编号而不是 MY_SWITCH_CELL。很好的全方位解决方案!
    • @Jesse 'aCell.accessoryView = switchView;'完全等同于“[aCell setAccessoryView:switchView];”。你有什么理由避免使用点符号吗?
    • 非常感谢您的回答!将开关添加为子视图会弄乱语音命令。将其设置为附件视图与画外音完美搭配!
    • 如何知道被选中的开关的索引?
    • @doxsi switchView.tag = indexPath.row 用于检测哪个行开关更改为 swift
    【解决方案5】:

    您可以在 Interfacebuilder 中准备单元格,将其链接到 Viewcontroller 的 IBOutlet 并在 tableview 要求正确的行时返回它。

    相反,您可以为单元创建单独的 xib(同样使用 IB)并在单元创建时使用 UINib 加载它。

    最后,您可以通过编程方式创建开关并将其添加到您的单元格内容视图或附件视图中。

    哪一种最适合你,很大程度上取决于你喜欢做什么。如果您的 tableviews 内容是固定的(对于设置页面等),前两个可能效果很好,如果内容是动态的,我更喜欢编程解决方案。请更具体地说明您想做什么,这样会更容易回答您的问题。

    【讨论】:

    • 我更喜欢编程解决方案(尽管它用于设置页面),但我也对前两个选项的工作原理感兴趣。也许你可以更详细地解释一下。
    【解决方案6】:

    您可以将 UISwitch 或任何其他控件添加到单元格的accessoryView。这样它就会出现在单元格的右侧,这可能是您想要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 2016-10-09
      • 1970-01-01
      相关资源
      最近更新 更多