Deleting a Row from a UITableView in Swift?
Works for Swift 3 and Swift 4
Use the UITableViewDataSource tableView(:commit:forRowAt:)
method, see also this answer here:
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.catNames.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
Delete rows from tableview using swift
To define "[indexPath]". It becomes [IndexPath(row: indexPath.row, section: 0)]
tableView.deleteRows(at: [IndexPath(row: indexPath.row, section: 0)], with: .automatic)
or
recall the particular section in the table view also
This will work outside of the function
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
Deleting the bottom row of TableView
Edit 2
After some experimentation, it appears to be an issue with iOS 12
(at least, on my iOS 12.4
simulator and device).
This can be (somewhat) confirmed by
- launch the default iPhone Reminders app
- add a bunch of reminders (I just used A, B, C, etc...) so you have enough that scrolling is needed
- scroll down to the last row
- delete the last row
You'll see that the row deletion animation is faulty. In fact, deleting any row does not provide the smooth animation we see in iOS 13
.
Doing some searching I find similar issues back with iOS 7
reportedly fixed in iOS 8+
... so perhaps the same bug returned in one of the iOS 12
versions. You may be able to use one of those older work-arounds, but based on comments it was pretty hit-or-miss.
I still stand by my initial comment, though, that there is no reason for:
tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .fade)
to be called after the row deletion.
Original Answer
It sounds like you are doing too much...
This is all you should need to get the row to delete and the other rows to "slide down":
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
Results.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
No need to reload the data.
See example here: https://imgur.com/a/JvDQ1P6
Edit
Here is a complete (very simple) example. No @IBOutlet
or @IBAction
connections... just add a new table view controller to your Storyboard and assign its custom class to SampleTableViewController
:
class SampleCell: UITableViewCell {
let testView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .blue
return v
}()
let testLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .cyan
return v
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
@objc
func commonInit() -> Void {
contentView.addSubview(testView)
contentView.addSubview(testLabel)
let g = contentView.layoutMarginsGuide
// avoid constraint warnings
let c = testView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0)
c.priority = UILayoutPriority(rawValue: 999)
NSLayoutConstraint.activate([
c,
testView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
testView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
testView.heightAnchor.constraint(equalToConstant: 50.0),
testView.widthAnchor.constraint(equalTo: testView.heightAnchor),
testLabel.leadingAnchor.constraint(equalTo: testView.trailingAnchor, constant: 12.0),
testLabel.centerYAnchor.constraint(equalTo: testView.centerYAnchor),
testLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
])
}
}
class SampleTableViewController: UITableViewController {
var data: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
// fill data array with 30 strings
data = (1...30).map { "This is row \($0)" }
tableView.register(SampleCell.self, forCellReuseIdentifier: "SampleCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let c = tableView.dequeueReusableCell(withIdentifier: "SampleCell", for: indexPath) as! SampleCell
c.testLabel.text = data[indexPath.row]
return c
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
data.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
}
}
}
iOS Swift - Deleting row in tableview within a tableViewCell
The problem is not in beginUpdates
, endUpdates
etc. It's in ToDoTableViewCell
logics.
As the error text hints, you are deleting and/or inserting incorrect number of rows.
Consider this example:
You delete 1 object from your data source (i.e. toDos
), you call tableView.deleteRows(at: [indexPath], with: .fade)
for one indexPath
.
Have that been the case, everything would be fine. But the error says that you had 3 rows before the update, now you have 5 rows after the update. And remember, you deleted 1 row, so you should be having 2 rows. How could this happen?.. App crashes.
The problem is that you are inserting objects to your data source somewhere, but are not calling tableView.inserRows(...)
. You need to figure this out.
Tableview deleting rows and sections
Solution: just add inverted indexPath array. let invertedIndexPathes = selectedRows.sorted(by: >)
Fixed mechanism:
guard let selectedRows = self.tableView.indexPathsForSelectedRows,
let indexPath = self.tableView.indexPathForSelectedRow else { return }
let invertedIndexPathes = selectedRows.sorted(by: >)
self.tableView.beginUpdates()
for itemIndexPath in invertedIndexPathes {
self.dataSource[itemIndexPath.section].rows.remove(at: itemIndexPath.row)
self.tableView.deleteRows(at: [itemIndexPath], with: .fade)
self.tableView.reloadData()
}
if self.dataSource[indexPath.section].rows.isEmpty {
self.dataSource.remove(at: indexPath.item)
self.tableView.deleteSections(IndexSet(arrayLiteral: indexPath.section), with: .fade)
}
self.tableView.endUpdates()
How to delete a row from UITableView
1) The problem with deleting is
[categoryArray removeObjectAtIndex:indexPath.row];
Remove it from db too.
Once you delete the row, reload the tableView using [tableView reloadData]
2) There is no problem if it is the only one item
Edit:
This is the problem
[categoryArray removeObjectAtIndex:indexPath.row];
NSString *selectedCategory = [categoryArray objectAtIndex:indexPath.row];
You have deleted the value at indexPath.row from array after that accessing the value at same indexPath.row, obviously it will delete the next value only.. :)
So put that
NSString *selectedCategory = [categoryArray objectAtIndex:indexPath.row]
line before [categoryArray removeObjectAtIndex:indexPath.row];
Error when Removing Row from TableView (Swift)
self.sections[indexPath.section].items.remove(at: indexPath.row)
self.tableView.beginUpdates()
DispatchQueue.main.async {
tableView.deleteRows(at: [indexPath], with: .automatic)
self.tableView.endUpdates()
}
Try removing item from your data source before beginUpdates(). You can also just remove item from the data source and reload the table view as you are setting the animation option as automatic, so tableview will perform the preferable animation.
Related Topics
Instagram Hooks Pre-Select Media Issue
Create Singleton of a Viewcontroller in Swift 3
Changing Uitableview's Section Header/Footer Title Without Reloading the Whole Table View
How to Make Nsurlsession Post Request in Swift
The Sandbox Is Not in Sync with the Podfile.Lock-Ios
Swiftui Drag Gesture Across Multiple Subviews
Simulate Universal Gravitation for Two Sprite Kit Nodes
How to Change Status Bar Style - iOS 12
Disable Wkwebview for Opening Links to Redirect to Apps Installed on My Iphone
Posting Photos to Facebook Fan Page with iOS Sdk
Setkeepalivetimeout iOS Behavior, Exceeded 15 Wakes in 300 Sec
Uitextview Is Not Scrolled to Top When Loaded
Go VS. Return Button in iOS Keyboard for HTML Input Forms
Ios: One Ibaction for Multiple Buttons
Xcode 10 Build Fails with 'Command Compileswift Failed with a Nonzero Exit Code
Switching Between Text Fields on Pressing Return Key in Swift
Prevent Users from Modifying Part of the Text in Slcomposeviewcontroller