UISwitch in einer UITableView-Zelle

81

Wie kann ich einbetten? UISwitch in eine UITableViewZelle ? Beispiele finden Sie im Einstellungsmenü.

Meine aktuelle Lösung:

UISwitch *mySwitch = [[[UISwitch alloc] init] autorelease];
cell.accessoryView = mySwitch;
testen
quelle
3
Was ist falsch an der aktuellen Art und Weise, wie Sie es tun?
MobileMon

Antworten:

192

Das Festlegen als Zubehöransicht ist normalerweise der richtige Weg. Sie können es in einrichten. tableView:cellForRowAtIndexPath: Möglicherweise möchten Sie mit target / action etwas tun, wenn der Schalter umgelegt wird. Wie so:

- (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" );
}
zpasternack
quelle
1
Anstelle von MY_SWITCH_CELL sollte die entsprechende Zellennummer sein, denke ich. Schöne Allround-Lösung!
Testen
1
@Jesse 'aCell.accessoryView = switchView;' entspricht genau '[aCell setAccessoryView: switchView];'. Haben Sie einen Grund, die Punktnotation zu vermeiden?
Zpasternack
1
Vielen Dank für diese Antwort! Das Hinzufügen des Schalters als Unteransicht bringt die Voice-Over-Befehle durcheinander. Das Einstellen als Zubehöransicht funktioniert perfekt mit Voiceover!
Nitin Alabur
2
Woher wissen Sie den Index des ausgewählten Schalters?
Doxsi
2
@doxsi switchView.tag = indexPath.rowfür erkennen, welcher Zeilenschalter für schnell geändert
Nazmul Hasan
10

Sie können der Zelle einen UISwitch oder ein anderes Steuerelement hinzufügen accessoryView. Auf diese Weise wird es auf der rechten Seite der Zelle angezeigt, was wahrscheinlich das ist, was Sie wollen.

Echelon
quelle
8
if (indexPath.row == 0) {//If you want UISwitch on particular row
    UISwitch *theSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
    [cell addSubview:theSwitch];
    cell.accessoryView = theSwitch;
}
k-thorat
quelle
Warum benutzt du initWithFrame? Warum benutzt du addSubview? switchkann nicht als Variablenname verwendet werden.
Testen
Entschuldigung für den Schalternamen. Ich hatte einen Code. Ich habe gerade den Variablennamen darin geändert.
K-Thorat
Es hat bei mir funktioniert. Effektive Lösung mit weniger Code.
Kenan Karakecili
2
Ich konnte zu dieser Arbeit gelangen, indem ich nur die accessoryView-Eigenschaft der Zelle festlegte. Ich denke nicht, dass das Hinzufügen des Schalters als Unteransicht notwendig ist.
Johnnieb
2

Sie können die Zelle in Interfacebuilder vorbereiten, sie mit einem IBOutlet Ihres Viewcontrollers verknüpfen und zurückgeben, wenn die Tabellenansicht nach der richtigen Zeile fragt.

Stattdessen können Sie eine separate xib für die Zelle erstellen (erneut mit IB) und diese bei der Zellenerstellung mit UINib laden.

Schließlich können Sie den Switch programmgesteuert erstellen und zur Inhaltsansicht oder Zubehöransicht Ihrer Zellen hinzufügen.

Welches am besten zu Ihnen passt, hängt weitgehend davon ab, was Sie gerne tun. Wenn der Inhalt Ihrer Tabellenansichten festgelegt ist (für eine Einstellungsseite usw.), funktionieren die ersten beiden möglicherweise gut. Wenn der Inhalt dynamisch ist, würde ich die programmatische Lösung bevorzugen. Bitte geben Sie genauer an, was Sie tun möchten. Dies würde die Beantwortung Ihrer Frage erleichtern.

Toastor
quelle
Ich würde die programmatische Lösung bevorzugen (obwohl es sich um eine Einstellungsseite handelt), aber ich bin auch daran interessiert, wie die ersten beiden Optionen funktionieren. Vielleicht könnten Sie sie etwas genauer erklären.
Testen
0

für schnelle Benutzer

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

Dies ist eine vollständigere Lösung, bei der das Ein- und Ausschalten auf der Ansichtsebene (UITableViewCell) erfolgt und die Ereignisse über didSelectund an den tableView-Delegaten weiterleitet didDeselect:

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)
        }
    }
}

Und auf Ihren Delegierten


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
}
rgkobashi
quelle