滚动时TableViewCell中的Swift 3 UISwitch丢失状态 [英] Swift 3 UISwitch in TableViewCell loses State when scrolling

查看:110
本文介绍了滚动时TableViewCell中的Swift 3 UISwitch丢失状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这很奇怪:我刚刚建立了一个新的Single-View iOS项目并将TableView放入Main.storyboard中.在此TableView中,我放入了TableViewCell,在此Cell中,放入了UILabel和UISwitch. 为此,我创建了一个CocoaTouchClass MyTableViewCell并将其设置为Interfacebuilder中TableViewCell的类. 我将UILabel和UISwitch的插座连接到MyTableViewCell,以及该开关的操作. 我还连接了TableView的dataSource并将其委托给ViewController.

That's weird: I just set up a new Single-View iOS Project and put a TableView into the Main.storyboard. In this TableView I put a TableViewCell and into this Cell, I put an UILabel and an UISwitch. For this TableViewCell I created a CocoaTouchClass MyTableViewCell and set this for the TableViewCell's Class in Interfacebuilder. I connected Outlets for the UILabel and UISwitch to MyTableViewCell, as well as an action for the switch. Also I connected the TableView's dataSource and delegate to the ViewController.

所以,我认为这是设置表的基本内容.

So, as I think, basic stuff for setting up a table.

我的ViewController看起来像这样:

My ViewController looks like this:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var tableData = [[String: Bool]]()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    for index in 1...40 {
        self.tableData.append([String(index): index%2 == 0])
    }
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.tableData.count
}


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! MyTableViewCell
    let object = tableData[indexPath.row].first!

    cell.myLabel.text = object.key
    cell.mySwitch.setOn(object.value, animated: false)

    return cell
}

}

因此,我在表中填充了一些数据行,并每隔一秒钟打开一次UISwitch.

So, I populate the Table with some Rows of Data and switch every second UISwitch to on.

MyTableViewCell-Class也没什么特别的:

The MyTableViewCell-Class is nothing special as well:

class MyTableViewCell: UITableViewCell {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var mySwitch: UISwitch!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

@IBAction func switched(_ sender: UISwitch) {
    print("Switched: \(sender.isOn)")
}

}

好吧,启动iOS-Simulator,我看到了预期的表格. 40个表格行不适合在一个屏幕上显示,因此TableView可以滚动.

Ok, fire up the iOS-Simulator and I see the Table as expected. 40 Table-Lines don't fit on one screen, so the TableView makes itself scrollable.

现在:当我更改一个UISwitch的状态时,拖动TableView以使更改后的UISwitch离开视图,然后拖动TableView以使更改后的UISwitch再次可见,则将其更改回其初始状态. 切换事件会像应有的那样被触发.

Now: when I change the state of one UISwitch, and drag the TableView so the changed UISwitch gets out of view and then drag the TableView so the changed UISwitch gets visible again, it is changed back to its initial state. The Switch-event gets fired like it should.

那么,我在做什么错?我想念什么吗?

So, what am I doing wrong? Am I missing something?

我录制了一个4秒的截屏视频,以演示发生了什么事情: http://b-bereich.de/download/swiftSwitch.mov

I recorded a 4-seconds-Screencast to demonstrate, what's going on: http://b-bereich.de/download/swiftSwitch.mov

推荐答案

TableViewCells已 重用 .

TableViewCells are reused.

这意味着您需要跟踪用于填充单元格内容的数据.如果单元格内容发生更改(例如,当您点击单元格中的开关"时),则需要更新您的数据源.当您滚动并再次显示该行时,您的数据将知道如何设置Switch的状态.

That means you need to keep track of the data you are using to fill the content of the cells. If the cell content changes - such as when you tap a Switch in the cell - you need to update your datasource. When you scroll, and that row is displayed again, your data will know how to set the state of the Switch.

这是一个简单的例子:

//
//  TableWithSwitchTableViewController.swift
//  SWTemp2
//
//  Created by Don Mag on 6/5/17.
//  Copyright © 2017 DonMag. All rights reserved.
//

import UIKit

class MyTableViewCell: UITableViewCell {
    @IBOutlet weak var myLabel: UILabel!
    @IBOutlet weak var mySwitch: UISwitch!

    var switchTapAction : ((Bool)->Void)?

    @IBAction func switched(_ sender: UISwitch) {
        print("Switched: \(sender.isOn)")

        // send the Switch state in a "call back" to the view controller
        switchTapAction?(sender.isOn)
    }
}

// simple data object
class MyObject: NSObject {
    var theTitle = ""
    var theSwitchState = false

    init(_ title: String) {
        theTitle = title
    }
}

class TableWithSwitchTableViewController: UITableViewController {

    // array of MyObjects
    var myData = [MyObject]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // just to make it a little easier to see the rows scroll
        tableView.rowHeight = 60

        // create 40 data objects for the table
        for i in 1...40 {
            let d = MyObject("Data Item: \(i)")
            myData.append(d)
        }

        tableView.reloadData()

    }

    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myData.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SwitchCell", for: indexPath) as! MyTableViewCell

        // Configure the cell...
        let d = myData[indexPath.row]
        cell.myLabel.text = d.theTitle
        cell.mySwitch.isOn = d.theSwitchState

        // set a "Callback Closure" in the cell
        cell.switchTapAction = {
            (isOn) in
            // update our Data Array to the new state of the switch in the cell
            self.myData[indexPath.row].theSwitchState = isOn
        }

        return cell
    }


}

这篇关于滚动时TableViewCell中的Swift 3 UISwitch丢失状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆