滚动时TableViewCell中的Swift 3 UISwitch丢失状态 [英] Swift 3 UISwitch in TableViewCell loses State when scrolling
问题描述
这很奇怪:我刚刚建立了一个新的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屋!