98

I have a UITableView that is using a custom table cell and each cell has a UIWebView.

Because UIWebView took along time to load, i want to avoid reloading them at all cost. In some situations, I have all cells loaded, but their heights are messed up. Therefore, I need to "relayout" the table without triggering the "cellForRow" function.

  1. I definitely cannot use reloadData... as it will reload the cells again.
  2. I tried tableView.setNeedDisplay, setNeedsLayout etc, none of them is able to rearrange the table cells
  3. The only way it worked, is to call beginupdates/endupdates block, this block is able to relayout my table without firing cellForRow! BUT, I didnt want the animation! This block produces an animation effect but i do not want it...

How can I solve my problem?

Alessandro Francucci
  • 1,528
  • 17
  • 25
mkto
  • 4,584
  • 5
  • 41
  • 65

9 Answers9

221
[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];
Evgeny Shurakov
  • 6,062
  • 2
  • 28
  • 22
  • 1
    This is great! I find it has some most interesting applications. I found that reload sections method will always animate even if you pass in ```UITableViewRowAnimationNone```, but with this the animation can be easily bypassed! – Flying_Banana Apr 21 '15 at 15:11
83

One more way to do it using blocks

Obj-C

[UIView performWithoutAnimation:^{
   [self.tableView beginUpdates];
   [self.tableView endUpdates];
}];

Swift

UIView.performWithoutAnimation {
    tableView.beginUpdates()
    tableView.endUpdates()   
}
Dmitriy
  • 1,898
  • 1
  • 15
  • 24
5

Swifties I had to do the following for this to work:

// Sadly, this is not as simple as calling:
//      UIView.setAnimationsEnabled(false)
//      self.tableView.beginUpdates()
//      self.tableView.endUpdates()
//      UIView.setAnimationsEnabled(true)

// We need to disable the animations.
UIView.setAnimationsEnabled(false)
CATransaction.begin()

// And we also need to set the completion block,
CATransaction.setCompletionBlock { () -> Void in
    // of the animation.
    UIView.setAnimationsEnabled(true)
}

// Call the stuff we need to.
self.tableView.beginUpdates()
self.tableView.endUpdates()

// Commit the animation.
CATransaction.commit()
Neil Japhtha
  • 875
  • 10
  • 9
  • Helped me. Thanks. Important to put `setAnimationsEnabled(true)` inside the completion block. – Lasse Bunk May 25 '16 at 15:02
  • But this does not update Footer until you scroll the tableview. – Mr. Bean Nov 30 '17 at 05:46
  • @Mr.Bean what's the full case? (i.e. does your tableview always have a footer, are you trying to insert one or remove one?) – Neil Japhtha Dec 04 '17 at 11:25
  • Always have a Footer, just need to update the footer (i.e. There are 2 views inside the footer, need to hide/unhide the views depending on the condition.) – Mr. Bean Dec 04 '17 at 15:24
  • @Mr.Bean what does your update block contain? The most extendable method here would be to reload the section. – Neil Japhtha Dec 04 '17 at 18:07
5

working on my project, but not a common solution.

let loc = tableView.contentOffset
UIView.performWithoutAnimation {

    tableView.reloadData()

    tableView.layoutIfNeeded()
    tableView.beginUpdates()
    tableView.endUpdates()

    tableView.layer.removeAllAnimations()
}
tableView.setContentOffset(loc, animated: true)//animation true may perform better
hstdt
  • 5,652
  • 2
  • 34
  • 34
1

I prefer to have a smooth transition:

CGPoint offset = self.tableView.contentOffset;
[UIView transitionWithView:self.tableView duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
        [self.tableView reloadData];
        self.tableView.contentOffset = offset;
    } completion:nil];

give it a try.

Jorge Arimany
  • 5,814
  • 2
  • 28
  • 23
1

iOS disable animations in UITableView

From iOS v11 you should use the performBatchUpdates method instead of beginUpdates/endUpdates

UIView.performWithoutAnimation {
    self.tableView.performBatchUpdates {
        //table view updates
    }
}
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
0

I wanted to updated the cell height for section 5 and following code worked for me:

UiView.setAnimationsEnabled(False)
self.productTableView.reloadSections(NSIndexSet(index: SectionType.ProductDescription.hashValue), withRowAnimation: UITableViewRowAnimation.None)
self.productTableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 5), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)
UIView.setAnimationsEnabled(true)
Aadi007
  • 247
  • 2
  • 5
0

for OBJ-C

[UIView setAnimationsEnabled:NO];
[tableView beginUpdates];
[tableView endUpdates];
[UIView setAnimationsEnabled:YES];

for swift

UIView.setAnimationsEnabled(false)
tableView.beginUpdates()
tableView.endUpdates()
UIView.setAnimationsEnabled(true)
dimaskpz
  • 81
  • 8
-1

In my case worked this:

func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
    tableView.beginUpdates()
    tableView.endUpdates()
    return true
}

func textViewDidChange(_ textView: UITextView) {
    DispatchQueue.main.async {
        self.tableView.beginUpdates()
        self.tableView.endUpdates()
    }
}