iOS 11 Uitableview Delete Rows Animation Bug

iOS 11 UITableView delete rows animation bug

I have been having countless problems with iOS 11 UITableView. Going to every UITableView in my entire app and doing the following fixed all of my problems.

Set estimatedRowHeight, estimatedSectionHeaderHeight, and estimatedSectionFooterHeight to 0.

Source: iOS 11 Floating TableView Header

problems with animation when deleting the last row of a TableView in ios7

Its a bug of ios7.. the tablerow animations are broken!
My fix was to fadeOut the cell right before the tableViewRowAnimation..

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// hide cell, because animations are broken on ios7
double iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (iosVersion >= 7.0 && iosVersion <= 8.0) {
[tableView cellForRowAtIndexPath:indexPath].alpha = 0.0;
}

[tableView deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationMiddle];
}

Weird UITableView insert/delete row animation

You will have to call

[tableView beginUpdates] 

and

[tableView endUpdates] 

before and after calling insert/delete methods as below :

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2 + self.thirdCellVisible;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];

if (indexPath.row == 1)
{
if (self.thirdCellVisible)
{
self.thirdCellVisible = !self.thirdCellVisible;
[self.tableView beginUpdates];

[tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];

[self.tableView endUpdates];

}
else
{
self.thirdCellVisible = !self.thirdCellVisible;
[self.tableView beginUpdates];

[tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
withRowAnimation:UITableViewRowAnimationTop];

[self.tableView endUpdates];

}
}
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == self.thirdCellIndexPath.row)
{
return 100.0f;
}

return 44.0f;
}

Incorrect animation when reordering tableview with new iOS 11 APIs

Just change table deletion animation to .automatic, like so:

tableView.deleteRows(at: [sourceIndexPath], with: .automatic)

After that there won't be that weird animation.

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)
}
}
}

Unwanted UITableView reload animation when navigating from iOS 11 search controller

Personally, I would simply hide the searchView controller before presenting the new view controller.
( Using UIView.animates with a completion handler for example )

I would not try to investigate further because since iOS11, there is an esoteric problem in the safe area management. A bug ? :)

Even the launch screens layouts are not correctly handled.
So many majors logos miss their middle part at launch !



Related Topics



Leave a reply



Submit