UIRefreshControl with new card style modal

UIKit iOS13

In iOS 13, Apple brings new modal presentation style to the system. Users can pull down to dismiss the modal, and this is where the problem begins (or might not if you are always coding the right way).

New modal presentation style
New modal view in iOS 13

Problem

The problem we are going to talk about is UIRefreshControl, which has the same gesture as the new modal. Both UIRefreshControl and new modal activate once users drag scrollable content area downward when they are at the very top of that scrollable content.

Let's say you add a refresh control to a scroll view like this.

let refreshControl = UIRefreshControl()
scrollView.addSubview(refreshControl)

The above code would work fine on iOS 12 or earlier and produce something like this.

Refresh control in iOS 12
UIRefreshControl in iOS 12

But if you build and run the same code on iOS 13 device, this is what you will get.

Refresh control in iOS 13
UIRefreshControl in iOS 13

As you can see the dismissal gesture of new modal overrides the behavior of pull-down to refresh of UIRefreshControl.

Solution

The solution is easy, but it might not be obvious if the code above didn't upset you.

In iOS 10, Apple added a new property, refreshControl, to UIScrollView.

var refreshControl: UIRefreshControl? { get set }

This property should be used when you want to set up UIRefreshControl to any UIScrollView and its subclass, and this is where the solution lies.

Just assign refresh control to refreshControl, and that's all you need to do to fix the problem.

let refreshControl = UIRefreshControl()
scrollView.refreshControl = refreshControl
Refresh control in iOS 13
UIRefreshControl in iOS 13 (The right way)

Refresh control behavior will take precedence over the one from modal. Users can still dismiss by dragging down from the navigation bar.

Conclusion

All these years, you can add refresh control wrongly and get away with it, but with a coming of iOS 13, this is no longer a case. So do yourself a favor and search through all your codebase and remove those addSubview(refreshControl).

References

Modality changes in iOS13
refreshControl


← Home