I've implemented a drag-and-drop feature on a sample project, which is a TableView with multiple sections. The interaction works fine, however, when I try to move a single row section cell near its section footer, the app crashes.
example of the interaction that causes the crash
Here is the exception the debugger throws:
Swift/Array.swift:405: Fatal error: Array index is out of range
This is the code I've written so far:
class ViewController: UIViewController {
var data = [["1"],["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q"]]
let tableView: UITableView = {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.backgroundColor = .red
tableView.rowHeight = 55
tableView.sectionFooterHeight = 50
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
tableView.delegate = self
tableView.dataSource = self
tableView.dragDelegate = self
tableView.dragInteractionEnabled = true
tableView.register(ShippedProductCell.self, forCellReuseIdentifier: ShippedProductCell.cellID)
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource, UITableViewDragDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: ShippedProductCell.cellID) as! ShippedProductCell
let shippedProductData = data[indexPath.section][indexPath.row]
cell.label.text = shippedProductData
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section)"
}
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return "Footer"
}
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
guard indexPath.row != data[indexPath.section].count - 1 else { return [] }
let dragItem = UIDragItem(itemProvider: NSItemProvider())
dragItem.localObject = data[indexPath.section][indexPath.row]
return [ dragItem ]
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let mover = data[sourceIndexPath.section].remove(at: sourceIndexPath.row)
data[destinationIndexPath.section].insert(mover, at: destinationIndexPath.row)
print(data)
}
}
When doing some debugging I found that the destinationIndexPath.row was 1, but the section only has 1 row, which is out of bounds. I would really appreciate your help, thanks.