SNSのアプリなどでおなじみのタイムラインを下にフリックしてテーブルを更新させるためのコードです。
例として1から6までの数字が並んだテーブルがフリックする度に数字が2倍されていくというものを作ります。
この2倍する処理がネットワーク経由でデータを更新する処理だと思ってください。
UI部品の配置
- デフォルトのViewの中にTableViewを追加
- TableViewの中にTableViewCellを追加
- TableViewCellの中にLabelを追加

TableViewCellの設定
- UITableViewCellを継承した新しいクラス(NumberCell)を追加
- TableViewCellのIdentity Inspector→Custom Class→ClassにNumberCellを指定
- Attribute Inspector→Table View Cell→Identifierに識別子(numberCell)を指定
- Labelにカーソルを合わせてCtrlキーを押しながらNumberCellにドラッグしコネクションを設定


import Foundation
import UIKit
class NumberCell: UITableViewCell {
@IBOutlet weak var label: UILabel!
}
Labelの設定
- Labelの上下左右にスペースのConstraintを設定

ViewControllerの設定
- UITableViewDataSourceとUITableViewDelegateを継承
- UITableViewDataSourceとUITableViewDelegateの必須メソッドを実装
- UIRefreshControlオブジェクトを生成しUIRefreshControl.addTarget()でスワイプ時に呼ぶメソッド(refresh)を指定
- refreshControlオブジェクトをaddSubview()でTableViewにサブビューとして追加
- refreshを実装。必ずUIRefreshControl.endRefreshing()を呼ぶ
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
var numberList:[Int] = [1, 2, 3, 4, 5, 6]
var refreshControl:UIRefreshControl!
let semaphore = DispatchSemaphore(value: 1)
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "再読み込み中")
refreshControl.addTarget(self, action: #selector(ViewController.refresh), for: UIControlEvents.valueChanged)
tableView.addSubview(refreshControl)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func updateTable () {
//時間がかかる処理と想定してグローバルキューで実行
DispatchQueue.global().async {
for (i, num) in self.numberList.enumerated() {
self.numberList[i] = num * 2
}
DispatchQueue.main.async {
// UI更新はメインスレッドで実行
self.tableView.reloadData()
self.semaphore.signal()
}
}
}
//UIRefreshControl によって画面を縦にフリックしたあとに呼ばれる
@objc func refresh() {
updateTable()
// 別スレッドでの処理が終了するのを待つ
semaphore.wait()
semaphore.signal()
//この処理の前にbeginRefreshingが呼ばれているはずなので終了する
refreshControl.endRefreshing()
}
//UITableViewDataSourceプロトコルの必須メソッド
//テーブルの行数を返す
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberList.count
}
//UITableViewDataSourceプロトコルの必須メソッド
//指定行のセルデータを返す
internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "numberCell", for: indexPath) as? NumberCell else {
return UITableViewCell()
}
cell.label.text = String(numberList[indexPath.row])
return cell
}
//UITableViewDelegateプロトコルの必須メソッド
//行をタップされたときに呼ばれる
func tableView(_ tableView: UITableView, didSelectRowAt indexPath:IndexPath) {
print(numberList[indexPath.row])
}
}