UISwitch w komórce UITableView

82

Jak mogę osadzić UISwitchna UITableViewkomórce? Przykłady można zobaczyć w menu ustawień.

Moje obecne rozwiązanie:

UISwitch *mySwitch = [[[UISwitch alloc] init] autorelease];
cell.accessoryView = mySwitch;
testowanie
źródło
3
Co jest nie tak z obecnym sposobem, w jaki to robisz?
MobileMon

Odpowiedzi:

193

Ustawienie go jako accessoryView jest zwykle najlepszym rozwiązaniem. Możesz to ustawić w opcji tableView:cellForRowAtIndexPath: Możesz użyć celu / akcji, aby zrobić coś, gdy przełącznik jest odwrócony. Tak jak to:

- (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
źródło
1
Myślę, że zamiast MY_SWITCH_CELL powinien być odpowiedni numer komórki. Ładne rozwiązanie dookoła!
testowanie
1
@Jesse 'aCell.accessoryView = switchView;' jest dokładnie równoważne z „[aCell setAccessoryView: switchView];”. Czy masz jakiś powód, aby unikać notacji z kropką?
zpasternack
1
Dziękuję bardzo za tę odpowiedź! Dodanie przełącznika jako widoku podrzędnego zakłóca działanie poleceń głosowych. Ustawienie go jako widoku akcesoriów działa idealnie z podkładem głosowym!
Nitin Alabur
2
Skąd znasz indeks wybranego przełącznika?
doxsi,
2
@doxsi, switchView.tag = indexPath.rowaby wykryć, który przełącznik wiersza został zmieniony na szybki
Nazmul Hasan
10

Możesz dodać UISwitch lub dowolną inną kontrolkę do komórki accessoryView. W ten sposób pojawi się po prawej stronie komórki, co prawdopodobnie jest tym, czego chcesz.

Rzut
źródło
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
źródło
Dlaczego używasz initWithFrame? Dlaczego używasz addSubview? switchnie można użyć jako nazwy zmiennej.
testowanie
Przepraszamy za nazwę przełącznika. Miałem jakiś kod ... Właśnie zmieniłem w nim nazwę zmiennej.
k-thorat
U mnie to zadziałało. Skuteczne rozwiązanie z mniejszą ilością kodu.
Kenan Karakecili
2
Udało mi się przejść do tej pracy, ustawiając tylko właściwość accessoryView komórki. Nie sądzę, aby dodanie przełącznika jako widoku podrzędnego było konieczne.
johnnieb
2

Możesz przygotować komórkę w Interfacebuilder, połączyć ją z IBOutlet twojego Viewcontroller i zwrócić ją, gdy tabela zapyta o właściwy wiersz.

Zamiast tego możesz utworzyć oddzielny xib dla komórki (ponownie z IB) i załadować go przy użyciu UINib podczas tworzenia komórek.

Na koniec możesz utworzyć przełącznik programowo i dodać go do widoku zawartości komórek lub widoku akcesoriów.

To, który z nich najbardziej Ci odpowiada, zależy w dużej mierze od tego, co lubisz robić. Jeśli zawartość Twoich widoków tabel jest stała (dla strony ustawień itp.), Pierwsze dwie mogą dobrze działać, jeśli zawartość jest dynamiczna, wolę rozwiązanie zautomatyzowane. Podaj bardziej szczegółowe informacje, co chciałbyś zrobić, ułatwi to odpowiedź na Twoje pytanie.

Toastor
źródło
Wolałbym rozwiązanie zautomatyzowane (mimo że dotyczy strony ustawień), ale interesuje mnie też, jak działają dwie pierwsze opcje. Może mógłbyś wyjaśnić je trochę bardziej szczegółowo.
testowanie
1

Jest to bardziej kompletne rozwiązanie, w którym wyłączanie i włączanie odbywa się na warstwie widoku (UITableViewCell) i przekazuje zdarzenia do delegata tableView za pośrednictwem didSelecti 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)
        }
    }
}

I na twojego delegata


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
źródło
0

dla szybkich użytkowników

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .default, reuseIdentifier: "TableIdentifer")
        let switch = UISwitch()
        cell.accessoryView = switch 
}
king_T
źródło