見出し画像

【徒然iOS】気ままにUIKit96〜Table View Controller テーブルをビヨーンと引っ張って更新〜

概要

このマガジンは四十を過ぎたおっさんが、

を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。

今回

をハイ、レッツゴ🕺

前準備

念の為、

  1. バックアップ

をいつも通りやってから本題へ💃

てな感じで💦

本題

リフレッシュコントロールとは、

テーブルを下に引っ張ったときにActive Indicator Viewを表示する機能
テーブルビューコントローラーはrefreshControlを持っている
👉プロパティにリフレッシュコントローラーのインスタンスを設定して、
テーブルビューを引っ張ったときに読込中マークが表示されるようになる

で軽くやってるね👀

⒈事前準備

新規でテーブルビューコントローラを配置
クラスを新規で追加
クラスを適用して〜〜〜
Identifierを設定
class MyRefreshTableViewController: UITableViewController {
    //表示データ
    var dataList = ["佐藤","鈴木", "高橋","田中","渡辺","伊藤","山本","中村","小林","加藤","吉田","山田","佐々木","山口","松本","井上","斎藤","木村","林","清水","山崎","池田","阿部","森","橋本","山下","石川","中島"]
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    //データを返すメソッド
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //セルを取得し、背景色と苗字を設定する。
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableCell", for:indexPath) as UITableViewCell
        cell.backgroundColor =  UIColor(red: CGFloat(drand48()+0.5), green: CGFloat(drand48()+0.5), blue: CGFloat(drand48()+0.5), alpha: 1.0)
        cell.textLabel?.text = dataList[indexPath.row]
        return cell
    }
    //データの個数を返すメソッド
    override func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        return dataList.count
    }
}

に書き換えて〜〜〜

ハイ、出来た🕺

以下は、大見出しごとに追ってく〜〜〜

リフレッシュコントロール

⒈コード組み込み

//
//  TestTableViewController.swift
//
import UIKit
class TestTableViewController: UITableViewController {
    //表示データ
    var dataList = ["佐藤","鈴木", "高橋","田中","渡辺","伊藤","山本","中村","小林","加藤","吉田","山田","佐々木","山口","松本","井上","斎藤","木村","林","清水","山崎","池田","阿部","森","橋本","山下","石川","中島"]
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //リフレッシュコントロールを作成する。
        let refresh = UIRefreshControl()
        //インジケーターの下に表示する文字列を設定する。
        refresh.attributedTitle = NSAttributedString(string: "読込中")
        //インジケーターの色を設定する。
        refresh.tintColor = UIColor.blueColor()
        //テーブルビューを引っ張ったときの呼び出しメソッドを登録する。
        refresh.addTarget(self, action: "refreshTable", forControlEvents: UIControlEvents.ValueChanged)
        //テーブルビューコントローラーのプロパティにリフレッシュコントロールを設定する。
        self.refreshControl = refresh
    }
    //テーブルビュー引っ張り時の呼び出しメソッド
    func refreshTable(){
        //配列に要素がある場合、要素の半分を削除する。
        if(dataList.count > 0) {
            dataList.removeRange(0...dataList.count/2)
        }
        //読込中の表示を見るためにあえて2秒スリープする。
        sleep(2)
        //テーブルを再読み込みする。
        tableView.reloadData()
        //読込中の表示を消す。
        refreshControl?.endRefreshing()
    }
    //データを返すメソッド
    override func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
        //セルを取得し、背景色と苗字を設定する。
        let cell = tableView.dequeueReusableCellWithIdentifier("TestCell", forIndexPath:indexPath) as UITableViewCell
        cell.backgroundColor =  UIColor(red: CGFloat(drand48()+0.5), green: CGFloat(drand48()+0.5), blue: CGFloat(drand48()+0.5), alpha: 1.0)
        cell.textLabel?.text = dataList[indexPath.row]
        return cell
    }
    //データの個数を返すメソッド
    override func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        return dataList.count
    }
  }

を参考に〜〜〜

今回のコード(リフレッシュ)

class MyRefreshTableViewController: UITableViewController {
    //表示データ
    var dataList = ["佐藤","鈴木", "高橋","田中","渡辺","伊藤","山本","中村","小林","加藤","吉田","山田","佐々木","山口","松本","井上","斎藤","木村","林","清水","山崎","池田","阿部","森","橋本","山下","石川","中島"]
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //リフレッシュコントロールを作成する。
        let refresh = UIRefreshControl()
        //インジケーターの下に表示する文字列を設定する。
        refresh.attributedTitle = NSAttributedString(string: "読込中")
        //インジケーターの色を設定する。
        refresh.tintColor = UIColor.blue
        //テーブルビューを引っ張ったときの呼び出しメソッドを登録する。
        refresh.addTarget(
            self,
            action: #selector(self.refreshTable),
            for: UIControl.Event.valueChanged
        )
        //テーブルビューコントローラーのプロパティにリフレッシュコントロールを設定する。
        self.refreshControl = refresh
    }
    //テーブルビュー引っ張り時の呼び出しメソッド
    @objc func refreshTable(){
        //配列に要素がある場合、要素の半分を削除する。
        if(dataList.count > 0) {
            dataList.remove(at:dataList.count/2)
        }
        //読込中の表示を見るためにあえて2秒スリープする。
        sleep(2)
        //テーブルを再読み込みする。
        tableView.reloadData()
        //読込中の表示を消す。
        refreshControl?.endRefreshing()
    }
    //データを返すメソッド
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //セルを取得し、背景色と苗字を設定する。
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableCell", for:indexPath) as UITableViewCell
        cell.backgroundColor =  UIColor(red: CGFloat(drand48()+0.5), green: CGFloat(drand48()+0.5), blue: CGFloat(drand48()+0.5), alpha: 1.0)
        cell.textLabel?.text = dataList[indexPath.row]
        return cell
    }
    //データの個数を返すメソッド
    override func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        return dataList.count
    }
}

に書き換えて〜〜〜

⒉シミュレータで実行

起動後〜〜〜
リフレッシュ後〜〜〜
色が変わったね〜〜〜🕺

引っ張らずにインジケーターを表示する

⒈Screen Edge Pan Gesture Recognizerを追加し、Leftにチェック

選んで〜〜
追加後、Leftにチェック〜〜〜

⒉Screen Edge Pan Gesture Recognizerアクション接続

てな感じで〜〜〜

⒊コード組み込み

//
//  TestTableViewController.swift
//
import UIKit
class TestTableViewController: UITableViewController {
    //表示データ
    var dataList = ["佐藤","鈴木", "高橋","田中","渡辺","伊藤","山本","中村","小林","加藤","吉田","山田","佐々木","山口","松本","井上","斎藤","木村","林","清水","山崎","池田","阿部","森","橋本","山下","石川","中島"]
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //リフレッシュコントロールを作成する。
        let refresh = UIRefreshControl()
        //インジケーターの下に表示する文字列を設定する。
        refresh.attributedTitle = NSAttributedString(string: "読込中")
        //インジケーターの色を設定する。
        refresh.tintColor = UIColor.blueColor()
        //テーブルビューを引っ張ったときの呼び出しメソッドを登録する。
        refresh.addTarget(self, action: "refreshTable", forControlEvents: UIControlEvents.ValueChanged)
        //テーブルビューコントローラーのプロパティにリフレッシュコントロールを設定する。
        self.refreshControl = refresh
    }
    //画面左端ドラッグ時の呼び出しメソッド
    @IBAction func panLeftEdge(sender: UIScreenEdgePanGestureRecognizer) {
        if(sender.state == UIGestureRecognizerState.Began) {
            //ドラッグ開始時にインジケーターを表示する。
            tableView.setContentOffset(CGPointMake(0, -refreshControl!.frame.size.height), animated:true)
            refreshControl!.beginRefreshing()
        } else if(sender.state == UIGestureRecognizerState.Ended) {
            //ドラッグ終了時にテーブルを更新する。
            refreshTable()
        }
   }
    //テーブルビュー引っ張り時の呼び出しメソッド
    func refreshTable(){
        //配列に要素がある場合、要素の半分を削除する。
        if(dataList.count > 0) {
            dataList.removeRange(0...dataList.count/2)
        }
        //読込中の表示を見るためにあえて2秒スリープする。
        sleep(2)
        //テーブルを再読み込みする。
        tableView.reloadData()
        //読込中の表示を消す。
        refreshControl?.endRefreshing()
    }
    //データを返すメソッド
    override func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
        //セルを取得し、背景色と苗字を設定する。
        let cell = tableView.dequeueReusableCellWithIdentifier("TestCell", forIndexPath:indexPath) as UITableViewCell
        cell.backgroundColor =  UIColor(red: CGFloat(drand48()+0.5), green: CGFloat(drand48()+0.5), blue: CGFloat(drand48()+0.5), alpha: 1.0)
        cell.textLabel?.text = dataList[indexPath.row]
        return cell
    }
    //データの個数を返すメソッド
    override func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        return dataList.count
    }
  }

を参考に書き換え👀

実機でやっても左端はできない
セグエを無しにして、イニシャライズビューを今回のビューに切り替え
シミュレータはうまく反応しないので、実機でやると
確かにできた🕺

今回のコード(ジェスチャと組み合わせ)

class MyRefreshTableViewController: UITableViewController {
    //表示データ
    var dataList = ["佐藤","鈴木", "高橋","田中","渡辺","伊藤","山本","中村","小林","加藤","吉田","山田","佐々木","山口","松本","井上","斎藤","木村","林","清水","山崎","池田","阿部","森","橋本","山下","石川","中島"]
    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //リフレッシュコントロールを作成する。
        let refresh = UIRefreshControl()
        //インジケーターの下に表示する文字列を設定する。
        refresh.attributedTitle = NSAttributedString(string: "読込中")
        //インジケーターの色を設定する。
        refresh.tintColor = UIColor.blue
        //テーブルビューを引っ張ったときの呼び出しメソッドを登録する。
        refresh.addTarget(
            self,
            action: #selector(self.refreshTable),
            for: UIControl.Event.valueChanged
        )
        //テーブルビューコントローラーのプロパティにリフレッシュコントロールを設定する。
        self.refreshControl = refresh
    }
    //画面左端ドラッグ時の呼び出しメソッド
    @IBAction func myPanLeft(_ sender: UIScreenEdgePanGestureRecognizer) {
        if(sender.state == UIGestureRecognizer.State.began) {
            //ドラッグ開始時にインジケーターを表示する。
            tableView.setContentOffset(CGPointMake(0, -refreshControl!.frame.size.height), animated:true)
            refreshControl!.beginRefreshing()
        } else if(sender.state == UIGestureRecognizer.State.ended) {
            //ドラッグ終了時にテーブルを更新する。
            refreshTable()
        }
    }
    //テーブルビュー引っ張り時の呼び出しメソッド
    @objc func refreshTable(){
        //配列に要素がある場合、要素の半分を削除する。
        if(dataList.count > 0) {
            dataList.remove(at:dataList.count/2)
        }
        //読込中の表示を見るためにあえて2秒スリープする。
        sleep(2)
        //テーブルを再読み込みする。
        tableView.reloadData()
        //読込中の表示を消す。
        refreshControl?.endRefreshing()
    }
    //データを返すメソッド
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //セルを取得し、背景色と苗字を設定する。
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableCell", for:indexPath) as UITableViewCell
        cell.backgroundColor =  UIColor(red: CGFloat(drand48()+0.5), green: CGFloat(drand48()+0.5), blue: CGFloat(drand48()+0.5), alpha: 1.0)
        cell.textLabel?.text = dataList[indexPath.row]
        return cell
    }
    //データの個数を返すメソッド
    override func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
        return dataList.count
    }
}

注意点

インジケーターの文字列を設定するタイミングに注意

    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()  
        //テーブルビューコントローラーのプロパティにリフレッシュコントロールを設定する。
        self.refreshControl = UIRefreshControl()
        //インジケーターの下に表示する文字列を設定する。
        refreshControl!.attributedTitle = NSAttributedString(string: "読込中")
        //インジケーターの色を設定する。
        refreshControl!.tintColor = UIColor.blueColor()
        //テーブルビューを引っ張ったときの呼び出しメソッドを登録する。
        refreshControl!.addTarget(self, action: "refreshTable", forControlEvents: UIControlEvents.ValueChanged)
    }

のように、テーブルビューコントローラーのrefreshControlプロパティにリフレッシュコントロールのインスタンスを設定したあとに文字列を設定する
👉レコードの数が少ない状況ではアプリ起動時にいきなりインジケーターの文字列が表示る事象が発生(Swift 2.1、XCode 7.2)。

バグが解消されるまではrefreshControlプロパティにリフレッシュコントロールのインスタンスを設定するようにしよう。

てことなんだけど、

    //最初からあるメソッド
    override func viewDidLoad() {
        super.viewDidLoad()
        //テーブルビューコントローラーのプロパティにリフレッシュコントロールを設定する。
        self.refreshControl = UIRefreshControl()
        //インジケーターの下に表示する文字列を設定する。
        refreshControl!.attributedTitle = NSAttributedString(string: "読込中")
        //インジケーターの色を設定する。
        refreshControl!.tintColor = UIColor.blue
        //テーブルビューを引っ張ったときの呼び出しメソッドを登録する。
        refreshControl!.addTarget(self, action: #selector(self.refreshTable), for: UIControl.Event.valueChanged)
    }

でやっても、

別に読み込み中は表示されてない👀
すでにバグは解消されてる様子🕺

さてと、

ブラッシュアップ

このプロジェクトは、ナビゲーションコントローラで繋ぐので、元に戻す

ナビゲーションコントローラをis Initialに〜〜〜
セグエで繋いで〜〜〜
左から右だと、ナビゲーションビューの動きが優先されるので
右から左時に更新するように、Rightに変更してみる
何回か実機で試したけど、できた様子👀

ついでに余計なコードも全て削除した🕺

あとは、地球儀ボタンをいつも通り〜〜〜

追加して、いつも通り〜〜〜

記事公開後、

ハイ、完了💃
実機も問題無し🕺

Apple公式

さてと、次回は

をレッツゴする🕺

いよいよテーブルビューコントローラも最後だねえ

残り、12回

いいなと思ったら応援しよう!