この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは! 加藤潤です。
iOS 10で全てのスクロールビューでRefresh Controlがサポートされました!
今回はこの機能をご紹介したいと思います。
Refresh Controlとは
まずはごく簡単にRefresh Controlについて説明します。
Refresh Controlとは、テーブルビューのUIでよくある「引っ張って更新」するためのUIコンポーネントで、UIKitのクラスはUIRefreshControl
です。
iOS 9以前のUIRefreshControl
iOS 9までは、UIRefreshControl
を生成し、UITableViewController
のrefreshControl
プロパティにセットする形で使用していたかと思います。
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
refreshControl = UIRefreshControl()
refreshControl?.addTarget(self, action: #selector(ViewController.refresh(_:)), forControlEvents: .ValueChanged)
}
func refresh(sender: UIRefreshControl) {
// ここに通信処理などデータフェッチの処理を書く
// データフェッチが終わったらUIRefreshControl.endRefreshing()を呼ぶ必要がある
}
}
UIRefreshControlのクラスリファレンスを見ると、「Because the refresh control is specifically designed for use in a table view that's managed by a table view controller, using it in a different context can result in undefined behavior.」と記載されています。 実装についてWebを検索すると、UITableViewControllerを使わずにUIViewControllerで管理するUITableViewにUIRefreshControlをaddSubviewして使用する例が散見されますが、動作が保証されていないのでこれはやらない方が無難かと思います。
iOS 10以降のUIRefreshControl
iOS 10ではiOS 9までの方法も使えますが、以下のようにUIScrollView
のプロパティとしてrefreshControl
が追加されました。
@available(iOS 2.0, *)
open class UIScrollView : UIView, NSCoding {
・・・省略
@available(iOS 10.0, *)
open var refreshControl: UIRefreshControl?
}
UIViewControllerが管理するUITableViewでUIRefreshControlを使用する
UIScrollView
に追加されたrefreshControl
プロパティを利用すればUITableViewController
を使わずにUIRefreshControl
が使えます。
以下はUIViewController
が管理するUITableView
でUIRefreshControl
を使用する例です。
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
private let refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
tableView.refreshControl = refreshControl
refreshControl.addTarget(self, action: #selector(ViewController.refresh(sender:)), for: .valueChanged)
}
func refresh(sender: UIRefreshControl) {
// ここに通信処理などデータフェッチの処理を書く
// データフェッチが終わったらUIRefreshControl.endRefreshing()を呼ぶ必要がある
}
}
UICollectionViewでUIRefreshControlを使用する
もちろんUICollectionView
にも使えます。
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
private let refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.refreshControl = refreshControl
refreshControl.addTarget(self, action: #selector(ViewController.refresh(sender:)), for: .valueChanged)
}
func refresh(sender: UIRefreshControl) {
// ここに通信処理などデータフェッチの処理を書く
// データフェッチが終わったらUIRefreshControl.endRefreshing()を呼ぶ必要がある
}
}
UIScrollViewでUIRefreshControlを使用する
もう説明は不要かと思いますが、当然UIScrollView
でも使えます。
class ViewController: UIViewController {
@IBOutlet weak var scrollView: UIScrollView!
private let refreshControl = UIRefreshControl()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.refreshControl = refreshControl
refreshControl.addTarget(self, action: #selector(ViewController.refresh(sender:)), for: .valueChanged)
}
func refresh(sender: UIRefreshControl) {
// ここに通信処理などデータフェッチの処理を書く
// データフェッチが終わったらUIRefreshControl.endRefreshing()を呼ぶ必要がある
}
}
まとめ
UIScrollView
のプロパティとしてrefreshControl
が追加されたことでUITableViewController
に縛られずに使えるようになったことは嬉しいですね!