I think I can shed some light into when and how the spinners stop spinning in cells.
I’ve subclassed UIActivityIndicatorView with my own class overloading the startAnimating and stopAnimating functions and put breakpoints in them. I’ve made a simple cell with only a spinner on it of my class. I’ve set the spinner’s Animating property to true in IB:

Now here’s what happens. First two screenshots have a stack trace that indicates the two actions (stopping animations and starting them) are happening one after the other, in the same private function _didMoveFromWindow:toWindow:


It seems to me this is happening in the cell creation flow, so first it’s initialized with no animation and then the IB settings kick in and start the animation. Now here’s the interesting part, when the spinner stops animating:

So seems that the spinner keeps spinning when the cell is removed from the screen and is stopped when the cell is prepared to be shown on screen again (prepareForReuse) via the private function _removeAllAnimations, which seems to iterate recursively all child views.
The problem is that for some reason the UIKit’s private functions never re-enable the animations and the startAnimating never gets called. Actually IMO the disabling of animations is the real problem.
The solution that I propose, and it’s not perfect but it’s apparently what Apple expects of us, is subclassing the UITableViewCell for cells that contain spinners and re-enabling them in prepareForReuse:
class SpinnerCell: UITableViewCell {
@IBOutlet weak var spinner: UIActivityIndicatorView?
override func prepareForReuse() {
super.prepareForReuse()
if let spinner = self.spinner {
spinner.startAnimating()
}
}
}
Or in Obj-C:
@interface SpinnerCell
@property (weak) IBOutlet UIActivityIndicatorView *spinner;
@end
@implementation SpinnerCell
- (void)prepareForReuse {
[super prepareForReuse];
[self.spinner startAnimating];
}
@end