switch in a tableview with UserDefaults, several is activated by itself
Switch in a tableview with UserDefaults, several is activated by itself
有问题,我解释。
我想激活一个 Switch,可以在 tableView 中打开应用程序。
为此,我将标签保存在 NSUserDefault 中,如果打开应用程序,标签在 NSUserDefault 中,它会激活开关。
问题是,在下面的图片中,我只是打开了开关 A 和 B,但是当我滚动时,其他开关激活为 q、s、c,但从不相同。
你有什么想法可以建议我吗?
我但我的代码在控制台下面。
Screen 1
Screen 2
ViewController :
@IBOutlet weak var tableView_t: UITableView!
let station = ["A","B","C","D","E","F","G","H","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","&","é","("]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? TableViewCell
cell?.configCell(station[indexPath.item])
return cell!
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return station.count
}
表格视图单元格:
@IBOutlet weak var switch_t: UISwitch!
@IBOutlet weak var label_t: UILabel!
func configCell(_ labels : String)
{
label_t.text = labels
if let sav = UserDefaults.standard.value(forKey: "switch") as? [String]
{
print(sav)
for switchs in sav
{
print(switchs)
if switchs == labels
{
switch_t.setOn(true, animated: false)
print("On")
}
}
}
}
@IBAction func actionSwitch(_ sender: Any)
{
var sav : [String] = []
if let saving = UserDefaults.standard.value(forKey: "switch") as? [String]
{
sav = saving
}
if switch_t.isOn
{
sav.append(label_t.text!)
UserDefaults.standard.set(sav, forKey: "switch")
print(sav)
}
else
{
var number = 0
for s in sav
{
if s == label_t.text
{
sav.remove(at: number)
UserDefaults.standard.set(sav, forKey: "switch")
}
number += 1
print(sav)
}
}
}
控制台:
["A", "B"]
A
On
B
["A", "B"]
A
B
On
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
["A", "B"]
A
B
细胞得到重复利用。您必须始终为每个条件设置单元格的属性,以便为每个索引路径完全设置单元格。您的代码只处理打开单元格的开关,而不是关闭。
有两种解决方法。
- 更新您的
configCell
方法以在任何不应打开的情况下关闭开关。
- 覆盖单元格的
prepareForReuse
方法。在这种方法中,您应该重置单元格的所有状态。这包括将开关设置为关闭并清除标签的文本。
附带说明一下,您的代码还有其他几个小问题需要清理。
- 不要将键值编码与
UserDefaults
一起使用,除非您清楚地知道需要这样做。使用正确的方法保存和读取 UserDefaults
. 中的值
- 在您的
cellForRowAt
中,您应该将单元格强制转换为所需的类型。这使得该方法中的其余代码更易于编写,如果转换错误,您希望应用程序快速崩溃,因为这意味着您有需要修复的编程错误。
- Minor - 你的
configCell
方法的参数被称为 labels
但它只 repents 一个标签。给它一个复数名称会让人感到困惑。
- 您检查单元格开关是否应该打开的逻辑比需要的复杂得多。使用
Array
. 的contains
方法
- 您的更新代码
UserDefaults
比需要的更复杂。
- 您引用的是
IndexPath
的 item
属性。这意味着与 UICollectionView
一起使用。对于 UITableView
,使用 row
.
下面是解决上述所有问题后我将如何编写您的代码。
Table 控制器:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
cell.configCell(station[indexPath.row])
return cell
}
小区代码:
func configCell(_ label: String) {
label_t.text = label
if let sav = UserDefaults.standard.array(forKey: "switch") as? [String] {
switch_t.isOn = sav.contains(label)
} else {
switch_t.isOn = false
}
}
@IBAction func actionSwitch(_ sender: UISlider) {
var labels = (UserDefaults.standard.array(forKey: "switch") as? [String]) ?? []
if let text = label_t.text {
if switch_t.isOn {
labels.append(text)
} else {
if let index = labels.indexOf(text) {
labels.remove(at: index)
}
}
UserDefaults.standard.set(labels, forKey: "switch")
}
}
因为你从不在UserDefault中设置关闭标签时关闭。请尝试
switch_t.setOn(false, animated: false)
在适当的地方。
你需要弄清楚 iOS 不会为每一行创建新的单元格,它只是一次又一次地重复使用 1 个单元格,确保你的开关在显示下一个单元格之前打开或关闭,否则相同的状态会适用于其他..在你的情况下,你永远不会在单元格即将显示时关闭开关
switch_t.setOn(false, animated: true)
有问题,我解释。
我想激活一个 Switch,可以在 tableView 中打开应用程序。
为此,我将标签保存在 NSUserDefault 中,如果打开应用程序,标签在 NSUserDefault 中,它会激活开关。
问题是,在下面的图片中,我只是打开了开关 A 和 B,但是当我滚动时,其他开关激活为 q、s、c,但从不相同。
你有什么想法可以建议我吗? 我但我的代码在控制台下面。
Screen 1
Screen 2
ViewController :
@IBOutlet weak var tableView_t: UITableView!
let station = ["A","B","C","D","E","F","G","H","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","&","é","("]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? TableViewCell
cell?.configCell(station[indexPath.item])
return cell!
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return station.count
}
表格视图单元格:
@IBOutlet weak var switch_t: UISwitch!
@IBOutlet weak var label_t: UILabel!
func configCell(_ labels : String)
{
label_t.text = labels
if let sav = UserDefaults.standard.value(forKey: "switch") as? [String]
{
print(sav)
for switchs in sav
{
print(switchs)
if switchs == labels
{
switch_t.setOn(true, animated: false)
print("On")
}
}
}
}
@IBAction func actionSwitch(_ sender: Any)
{
var sav : [String] = []
if let saving = UserDefaults.standard.value(forKey: "switch") as? [String]
{
sav = saving
}
if switch_t.isOn
{
sav.append(label_t.text!)
UserDefaults.standard.set(sav, forKey: "switch")
print(sav)
}
else
{
var number = 0
for s in sav
{
if s == label_t.text
{
sav.remove(at: number)
UserDefaults.standard.set(sav, forKey: "switch")
}
number += 1
print(sav)
}
}
}
控制台:
["A", "B"] A On B ["A", "B"] A B On ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B ["A", "B"] A B
细胞得到重复利用。您必须始终为每个条件设置单元格的属性,以便为每个索引路径完全设置单元格。您的代码只处理打开单元格的开关,而不是关闭。
有两种解决方法。
- 更新您的
configCell
方法以在任何不应打开的情况下关闭开关。 - 覆盖单元格的
prepareForReuse
方法。在这种方法中,您应该重置单元格的所有状态。这包括将开关设置为关闭并清除标签的文本。
附带说明一下,您的代码还有其他几个小问题需要清理。
- 不要将键值编码与
UserDefaults
一起使用,除非您清楚地知道需要这样做。使用正确的方法保存和读取UserDefaults
. 中的值
- 在您的
cellForRowAt
中,您应该将单元格强制转换为所需的类型。这使得该方法中的其余代码更易于编写,如果转换错误,您希望应用程序快速崩溃,因为这意味着您有需要修复的编程错误。 - Minor - 你的
configCell
方法的参数被称为labels
但它只 repents 一个标签。给它一个复数名称会让人感到困惑。 - 您检查单元格开关是否应该打开的逻辑比需要的复杂得多。使用
Array
. 的 - 您的更新代码
UserDefaults
比需要的更复杂。 - 您引用的是
IndexPath
的item
属性。这意味着与UICollectionView
一起使用。对于UITableView
,使用row
.
contains
方法
下面是解决上述所有问题后我将如何编写您的代码。
Table 控制器:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
cell.configCell(station[indexPath.row])
return cell
}
小区代码:
func configCell(_ label: String) {
label_t.text = label
if let sav = UserDefaults.standard.array(forKey: "switch") as? [String] {
switch_t.isOn = sav.contains(label)
} else {
switch_t.isOn = false
}
}
@IBAction func actionSwitch(_ sender: UISlider) {
var labels = (UserDefaults.standard.array(forKey: "switch") as? [String]) ?? []
if let text = label_t.text {
if switch_t.isOn {
labels.append(text)
} else {
if let index = labels.indexOf(text) {
labels.remove(at: index)
}
}
UserDefaults.standard.set(labels, forKey: "switch")
}
}
因为你从不在UserDefault中设置关闭标签时关闭。请尝试
switch_t.setOn(false, animated: false)
在适当的地方。
你需要弄清楚 iOS 不会为每一行创建新的单元格,它只是一次又一次地重复使用 1 个单元格,确保你的开关在显示下一个单元格之前打开或关闭,否则相同的状态会适用于其他..在你的情况下,你永远不会在单元格即将显示时关闭开关
switch_t.setOn(false, animated: true)