無限リストを作成する練習をしてみました。
具体的なコードは最後に載せています。実際に動作するプロジェクトもGitHubにあげました。
動作
- 最初に10データ表示
- リストの最後が表示されると、最後尾に自動で5行追加
- リストの最初で引っ張られると、先頭に自動で2行追加
1.最初に10データ表示
Cellの使い回しを自動的にやってくれるらしいのでUITableViewControllerやUITableViewを使います。重くなるを防げるようになります。
モデルとしてDataクラス、モデルのリストにdataArray:[Data]を準備して、画面表示時にdataArrayに10データ作成しておきます。
2.リストの最後が表示されると、最後尾に自動で5行追加
StoryBoard
Prototype Cellをデータ用(identifier:dataCell)とフッター用(identifier:fotterCell)の2つ用意します。
numberOfSectionsInTableView
2を返すように設定します。
cellForRowAtIndexPath
section=0の時はデータ用、section=1の時はフッター用のCellを返すようにします。
willDisplayCell
再表示を含めセルが表示されるときには、willDisplayCellラベルをもつtableViewメソッドが呼ばれるようです。
section=1のときにdataArrayに5行追加してテーブル再更新をすれば完了です。
3.リストの最初で引っ張られると、先頭に自動で2行追加
引っ張る動作は、すでにフレームワークで準備されていました。出来合いの動作でいいのであれば、UIRefreshControlをTableViewに追加して、addTargetでコールバックするメソッド名を指定するだけです。便利です。
コールバックイベントが発生した時に、self.dataArray.insert(newData, atIndex: 0)で単純にデータ追加でとりあえずそれっぽい動きをするようになりました。
ただこの方法だとindexPathがUITableViewが管理している内容とずれるはずなので、Cellクラスを複数使う場合には、tableView.dequeueReusableCellWithIdentifier()の箇所で各Cellクラスにキャストする時につじつまが合わなくなるような気がしますが今週はここまで。
ソース
https://github.com/grachro/junk201408-swift-TableView-InfiniteScroll
// // ViewController.swift // junk201408-swift-TableView-InfiniteScroll // // Created by grachro on 2014/08/24. // Copyright (c) 2014年 grachro. All rights reserved. // import UIKit class ViewController: UIViewController ,UITableViewDelegate, UITableViewDataSource { @IBOutlet weak var tableView: UITableView! let refreshControl = UIRefreshControl() let DETA_SECTION = 0 let FOTTER_SECTION = 1 var dataArray:[Data] = [] //モデルのリスト let INIT_DATA_COUNT = 10 //初期表示データ let ADD_DATA_COUNT = 5 ///最後尾が表示された時に追加するデータ数 let REFLESH_DATA_COUNT = 2 ///引っ張られた時に上に追加するデータ数 override func viewDidLoad() { super.viewDidLoad() addDataAfter(INIT_DATA_COUNT) self.refreshControl.addTarget(self, action: "callbackRefreshControl", forControlEvents: UIControlEvents.ValueChanged) self.tableView.delegate = self; self.tableView.dataSource = self self.tableView.addSubview(self.refreshControl) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //UITableViewDataSource func numberOfSectionsInTableView(tableView: UITableView!) -> Int { return 2 } //UITableViewDataSource func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { switch section { case DETA_SECTION:return self.dataArray.count case FOTTER_SECTION:return 1 default:return 0 } } //UITableViewDataSource func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { switch indexPath.section { case DETA_SECTION: let cell = tableView.dequeueReusableCellWithIdentifier("dataCell", forIndexPath: indexPath) as DataCell let data = self.dataArray[indexPath.row] cell.setCaption("Dataセル セクション:\(data.index) \(data.caption)") return cell case FOTTER_SECTION: let cell = tableView.dequeueReusableCellWithIdentifier("fotterCell", forIndexPath: indexPath) as UITableViewCell return cell default:return UITableViewCell() } } //UITableViewDelegate func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat { return 40 } //UITableViewDelegate func tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell!, forRowAtIndexPath indexPath: NSIndexPath!) { //2つ目のセクションが表示されたら、モデルにデータ追加 if indexPath.section == FOTTER_SECTION { addDataAfter(ADD_DATA_COUNT) self.tableView.reloadData() } } //モデル操作 private func addDataAfter(count:Int) { for i in 0..<count { let last:Data? = self.dataArray.last let baseIndex = last == nil ? -1 : last!.index let newIndex = baseIndex + 1 let newData = Data(index: newIndex,caption: "\(newIndex)行目") self.dataArray.append(newData) } } //UIRefreshControl func callbackRefreshControl(){ addDataBefore(REFLESH_DATA_COUNT) self.tableView.reloadData() self.refreshControl.endRefreshing() } //モデル操作 private func addDataBefore(count:Int) { for i in 0..<count { let first:Data = self.dataArray.first! let baseIndex = first.index let newIndex = baseIndex - 1 let newData = Data(index: newIndex,caption: "\(newIndex)行目") self.dataArray.insert(newData, atIndex: 0) } } }