下にスワイプししたらTableViewがリロードされてParseからデータ更新するのをSwiftで書いた（Swift, Xcode6 beta5, Parse, UITableView）


# A. 概要
- iOSにデフォルトでついている「下に引っ張るとリロード」をSwiftで書いてみました
- リロードされる内容はTableView全体
- おまけでNavigation Bar Buttonにも更新ボタンをつけてみた

![refresh.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/27810/7bcd1c07-3c6a-d145-5024-a5872a680653.gif)

（上のgifでは、Parseの方で新たにデータを登録してみて、その後更新をして、登録したデータが反映されているかをチェックしている動画です。）

# B. 環境
- Swift
- Xcode6 beta5
- Parse.com

# C. Github
- この記事の内容を使っているプロジェクト -> [SwiftAndParseApp](https://github.com/kiiita/SwiftAndParseApp)
 - この記事に関するコミット -> [Add refreshing functions](https://github.com/kiiita/SwiftAndParseApp/commit/1a5e907b1ef480557ac3121665b033d19f184be4)

# 1. Parseからデータを読み込む関数を作る
```timelineTableViewController
class TimelineTableViewController: UITableViewController {
    
    var timelineData:NSMutableArray = NSMutableArray()
    
    required init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder)
    }
    
    func loadData(){
        timelineData.removeAllObjects()
        
        // call databases
        var findTimelineData:PFQuery = PFQuery(className: "Tweets")
        
        findTimelineData.findObjectsInBackgroundWithBlock{
            (objects:[AnyObject]!, error:NSError!)->Void in
            
            if !error{
                for object in objects{
                    self.timelineData.addObject(object)
                }
                
                let array:NSArray = self.timelineData.reverseObjectEnumerator().allObjects
                self.timelineData = array as NSMutableArray
                
                self.tableView.reloadData()
            }
        }
    }

	override func viewDidAppear(animated: Bool) {
        
        // Controller読み込み時にデータを取得。これは「下に引っ張って更新」とは関係無い。
        self.loadData()
		...
	}
```

# 2. 「下に引っ張って更新」の部分を作る
```timelineTableViewController.swift
override func viewDidLoad() {
        super.viewDidLoad()
		
		// 下記を追加
        var refresh = UIRefreshControl()
        refresh.attributedTitle = NSAttributedString(string: "Loading...") // Loading中に表示する文字を決める
        refresh.addTarget(self, action: "pullToRefresh", forControlEvents:.ValueChanged)
        
        self.refreshControl = refresh
    }
    
	// 何を更新するのかを定義
    func pullToRefresh(){
        self.loadData() // 先ほど1で書いたParseからデータを取る関数を呼び出す
        refreshControl.endRefreshing() // データが取れたら更新を終える（くるくる回るViewを消去）
        self.tableView.reloadData() // tableView自身を再読み込み
        println("reload finised")
        
    }
```
- 最後の ```self.tableView.reloadData()```を書かないと、データを書き換える前にLoadingのViewが消えてクラッシュしてしまいました。

# 3. tableViewに関連するその他のコード

```timelineTableViewController.swift

    override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        // データの数だけrowを返す
        return timelineData.count
    }

    
    override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let cell:TweetTableViewCell = tableView!.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as TweetTableViewCell
        
        let tweet:PFObject = self.timelineData.objectAtIndex(indexPath!.row) as PFObject
        
        // デザイン部分
        cell.tweetTextView.alpha = 0
        cell.timestampLabel.alpha = 0
        cell.usernameLabel.alpha = 0
        
        // Tweetの内容をParse.comから取得
        cell.tweetTextView.text = tweet.objectForKey("content") as String
        
        var dataFormatter:NSDateFormatter = NSDateFormatter()
        dataFormatter.dateFormat = "yyyy-MM-dd HH:mm"
        cell.timestampLabel.text = dataFormatter.stringFromDate(tweet.createdAt)
        
        // objectIdをforeignKeyとして、user(tweeter)を取得
        var findTweeter:PFQuery = PFUser.query()
        findTweeter.whereKey("objectId", equalTo: tweet.objectForKey("tweeter").objectId)
        
        findTweeter.findObjectsInBackgroundWithBlock{
            (objects:[AnyObject]!, error:NSError!)->Void in
            if !error{
                let user:PFUser = (objects as NSArray).lastObject as PFUser
                cell.usernameLabel.text = "@\(user.username)"
                
                
                // CELLの表示を少しずつずらす
                UIView.animateWithDuration(0.5, animations: {
                    cell.tweetTextView.alpha = 1
                    cell.timestampLabel.alpha = 1
                    cell.usernameLabel.alpha = 1
                    })
            }
        }

        // Configure the cell...

        return cell
    }
```

# 4. 更新ボタンをNavigation barに追加する
- ストーリーボードでBar Button Itemを追加する
- func loadData()に@IBActionを追加する

```timelineTableViewController.swift
@IBAction func loadData(){ // ココを追加する
        timelineData.removeAllObjects()
        
        // call databases
        var findTimelineData:PFQuery = PFQuery(className: "Tweets")
        
        findTimelineData.findObjectsInBackgroundWithBlock{
            (objects:[AnyObject]!, error:NSError!)->Void in
            
            if !error{
                for object in objects{
                    self.timelineData.addObject(object)
                }
                
                let array:NSArray = self.timelineData.reverseObjectEnumerator().allObjects
                self.timelineData = array as NSMutableArray
                
                self.tableView.reloadData()
            }
        }
    }
```

- ストーリーボードで先ほど追加したBar Button Itemをコントロール+クリックして、上記コードの所までドラッグすればOK


# D. 関連記事
- この記事の更新方法を実際に使ってみているプロジェクト
 - [mBaaSを使ってみよう！超簡単にSwiftでTwitterライクなポスト機能を作る(Xcode6 beta5, Parse.com)](http://qiita.com/kiiita/items/bc62293f6c4d479993c1)
 - [Swift & Parseを使ったユーザー登録、ログイン、ログアウト（Swift, Xcode6 beta5,Parse）](http://qiita.com/kiiita/items/1a1358437bb702a0af95)
- その他、Swiftで作ってみたもの
 - [SwiftのNotificationでHello, Worldして、アクションを3つ作ってみた(Xcode6 beta4)](http://qiita.com/kiiita/items/453426e3873e58dc8768)
 - [SwiftでTo Doリストを作ってみた（Xcode6 beta4, Tabbed Application, UITableView, UITextField）](http://qiita.com/kiiita/items/22bcb7c503eaa2f2d423)