在我的数组数组中删除一个条目时,程序在 swift 中崩溃
When deleting an entry in my array of arrays, the program crashes in swift
我有一个程序可以 sorts/displays 不同类别的表情符号。该程序有一个编辑按钮,用户可以在其中删除或移动“条目”,然后当他们单击“完成”时,程序会重新调整。数组应该更新,每个部分底部的 运行 总数也应该更新。
我不确定问题出在哪里。错误信息是:
"由于未捕获的异常 'NSInternalInconsistencyException',正在终止应用程序,原因:'无效更新:无效的部分数。更新 (3) 后 table 视图中包含的部分数必须是等于更新前 table 视图中包含的节数 (4),加上或减去插入或删除的节数(插入 0 个,删除 0 个)。
当前代码:
import UIKit
class EmojiTableViewController: UITableViewController {
var emojis: [[Emoji]] = [
[Emoji(symbol: "", name: "Grinning Face", description: "A typical smiley face.", usage: "happiness"),
Emoji(symbol: "", name: "Confused Face", description: "A confused, puzzled face.", usage: "unsure what to think; displeasure"),
Emoji(symbol: "", name: "Heart Eyes", description: "A smiley face with hearts for eyes.", usage: "love of something; attractive"),
Emoji(symbol: "", name: "Police Officer", description: "A police officer wearing a blue cap with a gold badge. He is smiling, and eager to help.", usage: "person of authority")],
[Emoji(symbol: "", name: "Turtle", description: "A cute turtle.", usage: "Something slow"),
Emoji(symbol: "", name: "Elephant", description: "A gray elephant.", usage: "good memory")],
[Emoji(symbol: "", name: "Spaghetti", description: "A plate of spaghetti.", usage: "spaghetti")],
[Emoji(symbol: "", name: "Die", description: "A single die.", usage: "taking a risk, chance; game"),
Emoji(symbol: "⛺️", name: "Tent", description: "A small tent.", usage: "camping"),
Emoji(symbol: "", name: "Stack of Books", description: "Three colored books stacked on each other.", usage: "homework, studying"),
Emoji(symbol: "", name: "Broken Heart", description: "A red, broken heart.", usage: "extreme sadness"),
Emoji(symbol: "", name: "Snore", description: "Three blue \'z\'s.", usage: "tired, sleepiness"),
Emoji(symbol: "", name: "Checkered Flag", description: "A black and white checkered flag.", usage: "completion")]
]
let myTitles: [String] = ["PEOPLE", "ANIMALS", "FOOD", "OTHER"]
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
let label = UILabel()
label.frame = CGRect.init(x: 5, y: 5, width: headerView.frame.width-10, height: headerView.frame.height-10)
label.text = myTitles[section]
label.font = .systemFont(ofSize: 14)
label.textColor = .gray
headerView.addSubview(label)
return headerView
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
let label = UILabel()
label.frame = CGRect.init(x: 5, y: 5, width: headerView.frame.width-10, height: headerView.frame.height-10)
label.text = ("Total Emojis: \(emojis[section].count)")
label.font = .systemFont(ofSize: 12)
label.textColor = .gray
headerView.addSubview(label)
return headerView
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem
}
@IBAction func refreshData(_ sender: UIRefreshControl) {
tableView.reloadData()
sender.endRefreshing()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return emojis.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return emojis[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "emojiCell", for: indexPath)
let emoji = emojis[indexPath.section][indexPath.row]
cell.textLabel?.text = "\(emoji.symbol) - \(emoji.name)"
cell.detailTextLabel?.text = emoji.description
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You clicked at \(indexPath)")
}
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
print("You clicked emoji \(emojis[indexPath.row])")
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
emojis.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let movingEmoji = emojis.remove(at: fromIndexPath.row)
emojis.insert(movingEmoji, at: to.row)
}
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if let vc = segue.destination as? EmojiDetailViewController {
if let indexPath = tableView.indexPathForSelectedRow {
vc.emoji = emojis[indexPath.section][indexPath.row]
}
}
}
}
在这里您删除了整个部分,但只删除了 1 行来刷新 table,因此替换
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
emojis.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
有
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
emojis[indexPath.section].remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
我有一个程序可以 sorts/displays 不同类别的表情符号。该程序有一个编辑按钮,用户可以在其中删除或移动“条目”,然后当他们单击“完成”时,程序会重新调整。数组应该更新,每个部分底部的 运行 总数也应该更新。
我不确定问题出在哪里。错误信息是:
"由于未捕获的异常 'NSInternalInconsistencyException',正在终止应用程序,原因:'无效更新:无效的部分数。更新 (3) 后 table 视图中包含的部分数必须是等于更新前 table 视图中包含的节数 (4),加上或减去插入或删除的节数(插入 0 个,删除 0 个)。
当前代码:
import UIKit
class EmojiTableViewController: UITableViewController {
var emojis: [[Emoji]] = [
[Emoji(symbol: "", name: "Grinning Face", description: "A typical smiley face.", usage: "happiness"),
Emoji(symbol: "", name: "Confused Face", description: "A confused, puzzled face.", usage: "unsure what to think; displeasure"),
Emoji(symbol: "", name: "Heart Eyes", description: "A smiley face with hearts for eyes.", usage: "love of something; attractive"),
Emoji(symbol: "", name: "Police Officer", description: "A police officer wearing a blue cap with a gold badge. He is smiling, and eager to help.", usage: "person of authority")],
[Emoji(symbol: "", name: "Turtle", description: "A cute turtle.", usage: "Something slow"),
Emoji(symbol: "", name: "Elephant", description: "A gray elephant.", usage: "good memory")],
[Emoji(symbol: "", name: "Spaghetti", description: "A plate of spaghetti.", usage: "spaghetti")],
[Emoji(symbol: "", name: "Die", description: "A single die.", usage: "taking a risk, chance; game"),
Emoji(symbol: "⛺️", name: "Tent", description: "A small tent.", usage: "camping"),
Emoji(symbol: "", name: "Stack of Books", description: "Three colored books stacked on each other.", usage: "homework, studying"),
Emoji(symbol: "", name: "Broken Heart", description: "A red, broken heart.", usage: "extreme sadness"),
Emoji(symbol: "", name: "Snore", description: "Three blue \'z\'s.", usage: "tired, sleepiness"),
Emoji(symbol: "", name: "Checkered Flag", description: "A black and white checkered flag.", usage: "completion")]
]
let myTitles: [String] = ["PEOPLE", "ANIMALS", "FOOD", "OTHER"]
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
let label = UILabel()
label.frame = CGRect.init(x: 5, y: 5, width: headerView.frame.width-10, height: headerView.frame.height-10)
label.text = myTitles[section]
label.font = .systemFont(ofSize: 14)
label.textColor = .gray
headerView.addSubview(label)
return headerView
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
let label = UILabel()
label.frame = CGRect.init(x: 5, y: 5, width: headerView.frame.width-10, height: headerView.frame.height-10)
label.text = ("Total Emojis: \(emojis[section].count)")
label.font = .systemFont(ofSize: 12)
label.textColor = .gray
headerView.addSubview(label)
return headerView
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem
}
@IBAction func refreshData(_ sender: UIRefreshControl) {
tableView.reloadData()
sender.endRefreshing()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return emojis.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return emojis[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "emojiCell", for: indexPath)
let emoji = emojis[indexPath.section][indexPath.row]
cell.textLabel?.text = "\(emoji.symbol) - \(emoji.name)"
cell.detailTextLabel?.text = emoji.description
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You clicked at \(indexPath)")
}
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
print("You clicked emoji \(emojis[indexPath.row])")
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
emojis.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
let movingEmoji = emojis.remove(at: fromIndexPath.row)
emojis.insert(movingEmoji, at: to.row)
}
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if let vc = segue.destination as? EmojiDetailViewController {
if let indexPath = tableView.indexPathForSelectedRow {
vc.emoji = emojis[indexPath.section][indexPath.row]
}
}
}
}
在这里您删除了整个部分,但只删除了 1 行来刷新 table,因此替换
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
emojis.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
有
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
emojis[indexPath.section].remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}