我按照此处提供的所有步骤操作:The proper way to delete rows from UITableView and update array from NSUserDefaults in Swift / iOS
然而,导致错误,说;
'无效更新:第0部分中的行数无效。数量 更新(2)后必须包含在现有部分中的行 等于之前该部分中包含的行数 update(2),加上或减去插入或删除的行数 该部分(0插入,1删除)和加号或减号的数量 移入或移出该部分的行(0移入,0移出)。'
我创建了
class TableViewController:UITableViewController {
struct Section {
var sectionName: String!
var words: [String]!
init(title: String, word: [String]) {
self.sectionName = title
self.words = word
}
}
var arrayForRows = [String]()
var sections = [Section]()
func getData() -> [String] {
if let data = userDefaultDataSave.stringArray(forKey: "data") {
return data
}
return []
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
guard let data = dataDefaults.stringArray(forKey: "data") else {
return
}
arrayForRows = data as [String]
tableView.reloadData()
sections = [
Section(title: "A", word: []), // 1
Section(title: "B", word: []), //2
Section(title: "C", word: []),
Section(title: "D", word: []),
Section(title: "E", word: []),
Section(title: "F", word: []),
Section(title: "G", word: []),
Section(title: "H", word: []),
Section(title: "I", word: []),
Section(title: "J", word: []),
Section(title: "K", word: []),
Section(title: "L", word: []),
Section(title: "M", word: []),
Section(title: "N", word: []),
Section(title: "O", word: []),
Section(title: "P", word: []),
Section(title: "Q", word: []),
Section(title: "R", word: []),
Section(title: "S", word: []),
Section(title: "T", word: []),
Section(title: "U", word: []),
Section(title: "V", word: []),
Section(title: "W", word: []),
Section(title: "X", word: []),
Section(title: "Y", word: []),
Section(title: "Z", word: [])
]
let getAlphabetData = getData()
for a in getAlphabetData {
if a.hasPrefix("A") || a.hasPrefix("a") {
if sections[0].sectionName == "A" {
sections[0].words.append(a as String)
}
}
if a.hasPrefix("B") || a.hasPrefix("b") {
if sections[1].sectionName == "B" {
sections[1].words.append(a as String)
}
}
if a.hasPrefix("c") || a.hasPrefix("c") {
if sections[2].sectionName == "C" {
sections[2].words.append(a as String)
}
}
if a.hasPrefix("D") || a.hasPrefix("d") {
if sections[3].sectionName == "D" {
sections[3].words.append(a as String)
}
}
if a.hasPrefix("E") || a.hasPrefix("e") {
if sections[4].sectionName == "E" {
sections[4].words.append(a as String)
}
}
if a.hasPrefix("F") || a.hasPrefix("f") {
if sections[5].sectionName == "F" {
sections[5].words.append(a as String)
}
}
if a.hasPrefix("G") || a.hasPrefix("g") {
if sections[6].sectionName == "G" {
sections[6].words.append(a as String)
}
}
if a.hasPrefix("H") || a.hasPrefix("h") {
if sections[7].sectionName == "H" {
sections[7].words.append(a as String)
}
}
if a.hasPrefix("I") || a.hasPrefix("i") {
if sections[8].sectionName == "I" {
sections[8].words.append(a as String)
}
}
if a.hasPrefix("J") || a.hasPrefix("j") {
if sections[9].sectionName == "J" {
sections[9].words.append(a as String)
}
}
if a.hasPrefix("K") || a.hasPrefix("k") {
if sections[10].sectionName == "K" {
sections[10].words.append(a as String)
}
}
if a.hasPrefix("L") || a.hasPrefix("l") {
if sections[11].sectionName == "L" {
sections[11].words.append(a as String)
}
}
if a.hasPrefix("M") || a.hasPrefix("m") {
if sections[12].sectionName == "M" {
sections[12].words.append(a as String)
}
}
if a.hasPrefix("N") || a.hasPrefix("n") {
if sections[13].sectionName == "N" {
sections[13].words.append(a as String)
}
}
if a.hasPrefix("O") || a.hasPrefix("o") {
if sections[14].sectionName == "O" {
sections[14].words.append(a as String)
}
}
if a.hasPrefix("P") || a.hasPrefix("p") {
if sections[15].sectionName == "P" {
sections[15].words.append(a as String)
}
}
if a.hasPrefix("Q") || a.hasPrefix("q") {
if sections[16].sectionName == "Q" {
sections[16].words.append(a as String)
}
}
if a.hasPrefix("R") || a.hasPrefix("r") {
if sections[17].sectionName == "R" {
sections[17].words.append(a as String)
}
}
if a.hasPrefix("S") || a.hasPrefix("s") {
if sections[18].sectionName == "S" {
sections[18].words.append(a as String)
}
}
if a.hasPrefix("T") || a.hasPrefix("t") {
if sections[19].sectionName == "T" {
sections[19].words.append(a as String)
}
}
if a.hasPrefix("U") || a.hasPrefix("u") {
if sections[20].sectionName == "U" {
sections[20].words.append(a as String)
}
}
if a.hasPrefix("V") || a.hasPrefix("v") {
if sections[21].sectionName == "V" {
sections[21].words.append(a as String)
}
}
if a.hasPrefix("W") || a.hasPrefix("w") {
if sections[22].sectionName == "W" {
sections[22].words.append(a as String)
}
}
if a.hasPrefix("X") || a.hasPrefix("x") {
if sections[23].sectionName == "X" {
sections[23].words.append(a as String)
}
}
if a.hasPrefix("Y") || a.hasPrefix("y") {
if sections[24].sectionName == "Y" {
sections[24].words.append(a as String)
}
}
if a.hasPrefix("Z") || a.hasPrefix("z") {
if sections[25].sectionName == "Z" {
sections[25].words.append(a as String)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return sections.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50.0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return arrayForRows.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].sectionName
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// Cellに値を設定する.
cell.textLabel?.font = UIFont.systemFont(ofSize: 20)
cell.textLabel?.textColor = UIColor.black
cell.textLabel!.text = sections[indexPath.section].words[indexPath.row]
return cell
}
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.beginUpdates()
arrayForRows.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
let userDefaults = UserDefaults.standard
userDefaults.set(arrayForRows, forKey: "data")
tableView.endUpdates()
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
}
通过这种方式,从另一个Controller中,将值添加到Section的words
数组中;
class InputDataViewController: UIViewController {
// this function is written inside UITextView in this class.
//But I omitted here.
func addData(text: String) {
var data = self.getData()
data.insert(text as NSString, at: 0)
dataDefault.set(data, forKey: "data")
}
func getData() -> [String] {
if let data = dataDefault.stringArray(forKey: "data") {
return data
}
return []
}
}
有什么问题?从我看到它的方式来看,我可以理解,如果我没有明确地写tableView.reloadData()
或tableView.beginUpdates()
和endUpdates()
,但我做到了。导致此错误的原因是什么?你可以帮帮我吗?
感谢。
已更新
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return sections[section].words.count
}
另外,我发现如果我这样写,它就有用了。但是,从我的表视图中未删除所选的一个。无论我在一个部分中选择和删除了一行,我的表视图中都删除了第一个单词索引。删除的行在另一部分中。
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
// removeHistory(index: sections[indexPath.section].words[indexPath.row])
tableView.beginUpdates()
let indexSet = NSMutableIndexSet()
indexSet.add(indexPath.section)
//let indexSet = sections[indexPath.section].words[indexPath.row] as IndexSet
//sections.remove(at: indexPath.section)
sections[indexPath.section].words.remove(at: indexPath.row)
var data = getData()
data.remove(at: indexPath.row)
dataDefault.set(data, forKey: "data")
dataDefault.synchronize()
//tableView.deleteSections(indexSet, with: UITableViewRowAnimation.fade)
tableView.deleteRows(at: [indexPath], with: .fade)
tableView.endUpdates()
//
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
答案 0 :(得分:1)
每次添加或删除行时,都必须确保数据源保持一致。在您的情况下,您要移除arrayForRows
对象,但您的numberOfRows
使用完全不同的数据来源:sections[section].words.count
所以你应该
numberOfRows
不变,然后从sections[indexPath.section].words
数组nubmerOfRows
方法更改为返回arrayForRows.count
只需选择您的dataSource是什么,然后选择正确的选项。由于您有多个部分,因此您应该遵循第一个建议。
修改强>
您收到index out of bounds
错误,因为您似乎永远不会更新sections
数组。您应该为每个部分填写所有words
数组,对吗?但是根据你提供的代码来判断它们总是空的。
基本上你的实现应该是这样的:
sections
方法中更新viewWillAppear
数组。只需从UserDefaults循环遍历数组中的所有元素,并将每个元素放入正确的Section
对象中。将单词插入sections
数组的函数示例:
func insert(word: String) {
guard word.characters.count > 0 else { return }
let firstLetter = String(describing: word.characters.first).lowercased()
for var section in sections {
if section.title.lowercased().hasPrefix(firstLetter) {
section.words.append(word)
}
}
}
答案 1 :(得分:0)
也许问题是你在删除数据之前从表视图中删除了行?尝试从数组中删除对象,然后从tableView
中删除行 tableView.beginUpdates()
arrayForRows.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
let userDefaults = UserDefaults.standard
userDefaults.set(arrayForRows, forKey: "data")
tableView.endUpdates()
还试着看看你的numberOfRowsInSection方法。我想它应该返回
arrayForRows.count