在 swift 4.2 的 table 视图中保存勾选单元格的状态
Save the state of checkmarked cell in table view in swift 4.2
我在视图控制器中制作了一个 table 视图并以编程方式填充它。我可以根据需要一次在单元格上打勾,但是当我回到那个屏幕时,它不在那里。
这些是我的数组:
let devCourses = [("Sound"),("Vibrate"),("Both"),("None")]
let devCousesImages = [UIImage(named: "speaker"), UIImage(named: "Group 1094"), UIImage(named: "Group 1093"), UIImage(named: "speaker-1")]
这是我的 didSelectRowAt
代码:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
这是 didDeselectRowAt
的代码:
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell=tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as! VibTableViewCell
let courseTitle = devCourses[indexPath .row]
let Images = devCousesImages[indexPath .row]
cell.label.text=courseTitle
cell.label.textColor = UIColor.darkGray
cell.photo.image=Images
return cell
}
我希望当我回到屏幕时复选标记在那里
因为您想返回查看控制器以显示所选单元格。然后你要维护选定的单元格数组,然后在 viewDidLoad
/viewWillappear
中将选定的单元格设置为下面的代码
for index in selectedArray {
self.tableView.selectRow(at: IndexPath(row: index, section: 0), animated: false, scrollPosition: .none)
}
创建一个字典[IndexPath:Bool]
以跟踪选择了哪些行的状态。
var dict: [IndexPath:Bool] = [:]
在 tableView(_:, didSelectRowAt:)
中添加以下行:
dict[indexPath] = true
在 tableView(_:, didDeselectRowAt:)
中添加以下行:
dict[indexPath] = false
在tableView(_:, cellForRowAt:)
中添加以下行:
let selected = dict[indexPath] ?? false
cell.accessoryType = selected ? .checkmark : .none
首先使用一个结构作为数据源而不是多个数组。
也不要使用额外的数组或字典来维护选择,这很容易出错并且不必要地昂贵。
将布尔成员添加到所选状态的结构。
struct Course : Codable {
let name : String
let image : String
var isSelected : Bool
}
声明数据源数组
var courses = [Course(name: "Sound", image: "speaker", isSelected: false),
Course(name: "Vibrate", image: "Group 1094", isSelected: false),
Course(name: "Both", image: "Group 1093", isSelected: false),
Course(name: "None", image: "speaker-1", isSelected: false)]
在cellForRowAt
中根据isSelected
设置复选标记
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! VibTableViewCell
let course = courses[indexPath.row]
cell.label.text = course.name
// define the text color in Interface Builder
// cell.label.textColor = UIColor.darkGray
cell.photo.image = UIImage(named: course.image)
cell.accessoryType = course.isSelected ? .checkmark : .none
return cell
}
在 didSelectRowAt
中切换数据源中的 isSelected
值并重新加载行
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
courses[indexPath.row].isSelected.toggle()
tableView.reloadRows(at: indexPath, with: .none)
}
最后删除方法didDeselectRowAt
要保存你可以写的数组
do {
let data = try JSONEncoder().encode(courses)
UserDefaults.standard.set(data, forKey: "Courses")
} catch { print(error) }
你可以使用我的解决方案。
使用 NSCoder 在 plist 文件中保存单元格状态。即使您重新启动应用程序 - 您也不会丢失数据。
import UIKit
class TableViewController: UITableViewController {
var itemsArray : [Item] = [Item(name: "mom", done: true), Item(name: "pap", done: false), Item(name: "Lena", done: false), Item(name: "Gleb", done: false), Item(name: "Sasha", done: false), Item(name: "Max", done: false)]
/* path to custom plist file */
let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("Items.plist")
override func viewDidLoad() {
super.viewDidLoad()
if let filePath = dataFilePath {
print(filePath)
}
loadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return itemsArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let item = itemsArray[indexPath.row]
cell.accessoryType = item.done ? .checkmark : .none
cell.textLabel?.text = item.name
// Configure the cell...
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
itemsArray[indexPath.row].done = !itemsArray[indexPath.row].done
/* when state is changed - save it to plist file */
saveDate()
tableView.deselectRow(at: indexPath, animated: true)
}
/* save array to plist file (you can see it inside folder from consol) */
func saveDate() {
let encoder = PropertyListEncoder()
do {
let data = try encoder.encode(itemsArray)
try data.write(to: dataFilePath!)
} catch {
print(error.localizedDescription)
}
self.tableView.reloadData()
}
/* load data from plist file */
func loadData() {
if let data = try? Data(contentsOf: dataFilePath!) {
let decoder = PropertyListDecoder()
do {
itemsArray = try decoder.decode([Item].self, from: data)
} catch {
print(error.localizedDescription)
}
}
}
}
数据模型:
import Foundation
struct Item : Encodable, Decodable {
var name : String = ""
var done : Bool = false
}
我在视图控制器中制作了一个 table 视图并以编程方式填充它。我可以根据需要一次在单元格上打勾,但是当我回到那个屏幕时,它不在那里。
这些是我的数组:
let devCourses = [("Sound"),("Vibrate"),("Both"),("None")]
let devCousesImages = [UIImage(named: "speaker"), UIImage(named: "Group 1094"), UIImage(named: "Group 1093"), UIImage(named: "speaker-1")]
这是我的 didSelectRowAt
代码:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
这是 didDeselectRowAt
的代码:
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .none
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell=tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath) as! VibTableViewCell
let courseTitle = devCourses[indexPath .row]
let Images = devCousesImages[indexPath .row]
cell.label.text=courseTitle
cell.label.textColor = UIColor.darkGray
cell.photo.image=Images
return cell
}
我希望当我回到屏幕时复选标记在那里
因为您想返回查看控制器以显示所选单元格。然后你要维护选定的单元格数组,然后在 viewDidLoad
/viewWillappear
中将选定的单元格设置为下面的代码
for index in selectedArray {
self.tableView.selectRow(at: IndexPath(row: index, section: 0), animated: false, scrollPosition: .none)
}
创建一个字典[IndexPath:Bool]
以跟踪选择了哪些行的状态。
var dict: [IndexPath:Bool] = [:]
在 tableView(_:, didSelectRowAt:)
中添加以下行:
dict[indexPath] = true
在 tableView(_:, didDeselectRowAt:)
中添加以下行:
dict[indexPath] = false
在tableView(_:, cellForRowAt:)
中添加以下行:
let selected = dict[indexPath] ?? false
cell.accessoryType = selected ? .checkmark : .none
首先使用一个结构作为数据源而不是多个数组。
也不要使用额外的数组或字典来维护选择,这很容易出错并且不必要地昂贵。
将布尔成员添加到所选状态的结构。
struct Course : Codable {
let name : String
let image : String
var isSelected : Bool
}
声明数据源数组
var courses = [Course(name: "Sound", image: "speaker", isSelected: false),
Course(name: "Vibrate", image: "Group 1094", isSelected: false),
Course(name: "Both", image: "Group 1093", isSelected: false),
Course(name: "None", image: "speaker-1", isSelected: false)]
在cellForRowAt
中根据isSelected
设置复选标记
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! VibTableViewCell
let course = courses[indexPath.row]
cell.label.text = course.name
// define the text color in Interface Builder
// cell.label.textColor = UIColor.darkGray
cell.photo.image = UIImage(named: course.image)
cell.accessoryType = course.isSelected ? .checkmark : .none
return cell
}
在 didSelectRowAt
中切换数据源中的 isSelected
值并重新加载行
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
courses[indexPath.row].isSelected.toggle()
tableView.reloadRows(at: indexPath, with: .none)
}
最后删除方法didDeselectRowAt
要保存你可以写的数组
do {
let data = try JSONEncoder().encode(courses)
UserDefaults.standard.set(data, forKey: "Courses")
} catch { print(error) }
你可以使用我的解决方案。
使用 NSCoder 在 plist 文件中保存单元格状态。即使您重新启动应用程序 - 您也不会丢失数据。
import UIKit
class TableViewController: UITableViewController {
var itemsArray : [Item] = [Item(name: "mom", done: true), Item(name: "pap", done: false), Item(name: "Lena", done: false), Item(name: "Gleb", done: false), Item(name: "Sasha", done: false), Item(name: "Max", done: false)]
/* path to custom plist file */
let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("Items.plist")
override func viewDidLoad() {
super.viewDidLoad()
if let filePath = dataFilePath {
print(filePath)
}
loadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return itemsArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let item = itemsArray[indexPath.row]
cell.accessoryType = item.done ? .checkmark : .none
cell.textLabel?.text = item.name
// Configure the cell...
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
itemsArray[indexPath.row].done = !itemsArray[indexPath.row].done
/* when state is changed - save it to plist file */
saveDate()
tableView.deselectRow(at: indexPath, animated: true)
}
/* save array to plist file (you can see it inside folder from consol) */
func saveDate() {
let encoder = PropertyListEncoder()
do {
let data = try encoder.encode(itemsArray)
try data.write(to: dataFilePath!)
} catch {
print(error.localizedDescription)
}
self.tableView.reloadData()
}
/* load data from plist file */
func loadData() {
if let data = try? Data(contentsOf: dataFilePath!) {
let decoder = PropertyListDecoder()
do {
itemsArray = try decoder.decode([Item].self, from: data)
} catch {
print(error.localizedDescription)
}
}
}
}
数据模型:
import Foundation
struct Item : Encodable, Decodable {
var name : String = ""
var done : Bool = false
}