iOS drop down refresh UIScrollVie abnormal flashing problem

  • 2021-11-29 09:21:51
  • OfStack

It is said that it was after IOS8, but I encountered a problem in iOS10. The drop-down refresh used before may shake 1 time. When sliding quickly, after the drop-down is released, scrollView is about to return to the state of "refresh …".

Causes of jitter:


ScrollViewDidEndDragging => setContentInset:

In order to ensure that the drop-down refresh control can be displayed in the state of "Loading", we modified contentInset and added top of inset. Then why does this one-step operation cause scrollView to shake for 1 time?

I made a breakpoint in scrollViewDidScroll: to see what happened after setContentInset:. I set inset. top = 64; The results show that contentOffset of scrollView has changed like this:

(0, -64) = > (0, -133) = > (0, -64)

It can be seen from the above data that contentOffset was moved down by one segment in this process, and then returned to normal. Guess the cause of the problem:

After the drop-down is released, the bounce effect of scrollView itself conflicts with the current setting of inset

Initial attempt: async

Knowing the cause of the problem, my first thought was to avoid this conflict, so I called the method of setContentInset: asynchronously under 1:


dispatch_async(dispatch_get_main_queue(), ^{
      [UIView animateWithDuration:kAnimationDuration animations:^{
        self.scrollView.contentInset = inset;
      } completion:^(BOOL finished) {
      }];
    });

After one attempt, the problem is gone. However, some people have encountered such a problem later. After verification, it is true that this problem has not been completely fixed.

2 modifications: Forced contentOffset

Since it is caused by the change of contentOffset, I will set contentOffset again. So I tried twice:


dispatch_async(dispatch_get_main_queue(), ^{
      [UIView animateWithDuration:kAnimationDuration animations:^{
        self.scrollView.contentInset = inset;
        self.scrollView.contentOffset = CGPointMake(0, -inset.top);
      } completion:^(BOOL finished) {
      }];
    });

The test results found that it was useless, but the problem still existed. In this step, I spent a lot of time trying to solve the problem by other means, until I changed setContentOffset: method to setConentOffset: animated:. The problem is solved, and it can be seen that the implementation of these two methods in the system is different


dispatch_async(dispatch_get_main_queue(), ^{
      [UIView animateWithDuration:kAnimationDuration animations:^{
        self.scrollView.contentInset = inset;
        [self.scrollView setContentOffset:CGPointMake(0, -inset.top) animated:NO];
      } completion:^(BOOL finished) {
      }];
    });

Related articles: