How to handle RefreshControl in iOS

Issue #20

The other day I was doing refresh control, and I saw this Swift Protocols with Default Implementations as UI Mixins

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
extension Refreshable where Self: UIViewController
{
/// Install the refresh control on the table view
func installRefreshControl()
{
let refreshControl = UIRefreshControl()
refreshControl.tintColor = .primaryColor
refreshControl.addTarget(self, action: #selector(handleRefresh(_:)), for: .valueChanged)
self.refreshControl = refreshControl

if #available(iOS 10.0, *)
{
tableView.refreshControl = refreshControl
}
else
{
tableView.backgroundView = refreshControl
}
}
}

Protocol extension is cool but somehow I’m not a fan of it. I always consider composition first, to extract the specific task to one entity that does that well. It looks like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class RefreshHandler: NSObject {
let refresh = PublishSubject<Void>()
let refreshControl = UIRefreshControl()

init(view: UIScrollView) {
super.init()
view.addSubview(refreshControl)
refreshControl.addTarget(self, action: #selector(refreshControlDidRefresh(_: )), for: .valueChanged)
}

// MARK: - Action

func refreshControlDidRefresh(_ control: UIRefreshControl) {
refresh.onNext(())
}

func end() {
refreshControl.endRefreshing()
}
}

It is a bit Rx, we can use block if we like, but the idea is we can declare this RefreshHandler and use it everywhere we want

1
2
3
4
5
6
refreshHandler = RefreshHandler(view: scrollView)

refreshHandler.refresh
.startWith(())
.bindTo(viewModel.input.fetch)
.addDisposableTo(bag)

Comments