Tweetie で有名になった Pull to refresh ですが iOS 6 から UIRefreshControl
として OS 標準で追加されました。残念ながら UIRefreshControl
は UITableViewController
と一緒に使うしかまっとうな方法はありません。UIViewController
+ UITableView
のような構成で無理矢理使う方法を書いてみます。
重要
個人的におすすめしません。素直に UITableViewController
で使うような方向でまず実装を検討してください。これから紹介する方法は OS バージョン等の要因に左右されて期待するような動きをしない危険性があります。
方法
UIRefreshControl
を生成して UITableView
のインスタンスに addSubview するだけです。
ただし、これだけではアプリが Background から Foreground に戻ってきた時やタブの切り替え等で viewWillAppear などが呼ばれたあとに UIRefreshControl
が UITableView
よりも前面に出てくることがあります。
最前面に出てくるのをねじ伏せる方法
viewWillAppear で
[self fixRefreshControlLayout]; if (self.refreshControl.isRefreshing) { [self.tableView setContentOffset:self.scrollOffsetToRestore animated:NO]; }
というような感じにします。
- 1行目で
UIRefreshControl
のレイアウトを調整 - 2行目以降で refreshing 状態の時のために保持しておいた
UITableView
のcontentOffset
を復元させています。
1行目の fixRefreshControlLayout
はこんな感じ。
- (void)fixRefreshControlLayout { if ([self isViewLoaded] == NO) { return ; } BOOL isRefreshing = self.refreshControl.isRefreshing; if (isRefreshing) { [self.refreshControl endRefreshing]; } [self.refreshControl removeFromSuperview]; self.refreshControl = nil; [self.tableView addSubview:self.refreshControl]; if (isRefreshing) { [self.refreshControl beginRefreshing]; } }
最前面に出てきても再度 addSubview すれば期待する位置に出てきてくれるので念のため都度都度張り直しをしています。特にパフォーマンス上は大きな足かせにはなっていない印象です。
self.scrollOffsetToRestore
は viewWillDisappear:
のタイミングで現在の contentOffset を保持しておくようにしています。
まとめ
このような無理矢理な実装をしてねじ伏せるような実装を追加してもそんなに綺麗な感じじゃないです。ですので繰り返しになりますが素直な実装をとることを激しくおすすめします。Apple にはバグレポを通じて UIRefreshControl
が UITableViewController
に限定されずに使えるように要望しましょう。