[iOS] Swift で Twitter の Streaming API を叩く [Fabric]

## これはなに

以前の記事 (http://qiita.com/mokumoku/items/bf0460f420acac3c04fc) で Swift で簡単に TwitterAPI を叩くのを書きました。
これで機能最低限の Twitter クライアントが作れそうな感じがしましたが、やはり Streaming API に接続してリアルタイムに情報を受け取りたいものです。
Swift プロジェクトに Fabric Framework を導入してある前提で話を進めます。

## (その前に) REST API を叩く

REST API を叩くのには `TwitterKit` の機能が使えるので使います。
`Twitter.sharedInstance().APIClient.URLRequestWithMethod()` で `NSURLRequest` を作り
`Twitter.sharedInstance().APIClient.sendTwitterRequest()` で通信をします。
その結果をクロージャで受け取ってデータを整形したりします。例は以下。


```
let baseString = "https://api.twitter.com/v1.1"
let path = "/statuses/home_timeline.json"
let twtrRequest = Twitter.sharedInstance().APIClient.URLRequestWithMethod("GET", URL: baseString + request.path, parameters: nil, error: nil)
Twitter.sharedInstance().APIClient.sendTwitterRequest(twtrRequest) {
    (response, data, err) in
    switch (response, data, err) {
    case (.Some, .Some, .None):
        let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: nil)
        // JSONObject をアレコレする操作
    default:
        // エラー
    }
}
```

これで REST API は叩けるのですが、このまま EndPoint を Streaming API のものに差し替えてもうまくいきません。

## Streaming API を叩く

### Streaming API とは
[ドキュメントを読め](https://dev.twitter.com/streaming/overview)

要は

> ツイートデータへの低遅延なアクセスを開発者に提供する

ということで（一文目を訳しただけ）、ツイートやイベントがだらだらと流れてくるというものです。
能書きはこれくらいで接続してみましょう。

### NSURLConnection を使う

今回は `NSURLConnection` を使います。
「え？イマドキ `NSURLSession` を使うんじゃないの？」と思う人も多いと思いますが、それでできたら記事を書いてもらえると嬉しいです。

**2015/9/5 追記**
su_aska さんが解決してくださいました！ [こちらのコメント](http://qiita.com/mokumoku/items/00e4da028b4d64c9e8ff#comment-66cd591e37390403fecd)
`NSURLSessionDelegate` の `didReceiveChallenge`, `didReceiveResponse` でそれぞれ `completionHandler` を呼ばないといけなかったようです。
ありがとうございました！
**追記終わり**

`NSURLSession` だとうまくいかなかったので `NSURLConnection` を使いました。なぜうまくいかないのかは分かっていないので理由が分かればコメント等していただけると知識が深まると思います。

以下に例を示します。
`NSURLConnection` も `NSURLRequest` を必要とするのですが、ここは REST の時と同じように `TwitterKit` の機能を使って生成すればいいです。

```TwitterAPI.swift
class TwitterAPI: NSObject, NSURLConnectionDataDelegate, NSURLConnectionDelegate {
    func connectStream() {
        let endpoint = "https://userstream.twitter.com/1.1/statuses/sample.json"
        let twtrRequest = Twitter.sharedInstance().APIClient.URLRequestWithMethod("GET", URL: endpoint, parameters: nil, error: nil)
        let urlConnection = NSURLConnection(request: twtrRequest, delegate: self)
        urlConnection?.start()
    }

    // MARK: NSURLConnectionDelegate
    func connection(connection: NSURLConnection, didReceiveData data: NSData) {
        // ここにツイートが流れてくる
        let response: String = NSString(data: data, encoding: NSUTF8StringEncoding)!
        println(response)
    }
    
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        println((response as NSHTTPURLResponse).statusCode)
    }
    
    func connectionDidFinishLoading(connection: NSURLConnection) {
        println("connectionDidFinishLoading")
    }
}
```

これでどこからか `TwitterAPI().connectStream()` を読んであげればずらずらとツイートが流れてくるはずです。

いわゆる「ユーザーストリーム」に接続したければ [公式ドキュメント](https://dev.twitter.com/streaming/userstreams) を参考に EndPoint を変更したりすればいいと思います。

## やるべきこと

接続はできましたが、実際にクライアントを作ろうと思ったらやることがいくつかあるのでがんばります。

- UserStream は頻繁に切れるので、切れたら再接続するようにする
- Tweet 以外のイベント (fav, unfav, follow など) を処理する

イベント処理はJSONの中身を見ればいいだけなのでそんなに難しくないと思います。

## やらなくてもいいこと

- Fabric Framework(TwitterKit) を使う

Twitter ログインの認証情報を付加して `NSURLRequest` を作れれば Fabric を使う必要はありません。私も実際 `OAuthConsumer` を使ってやっていました。

- 上記のような実装を自分でする

今はライブラリもたくさんあって良いですね。[Swifter](https://github.com/mattdonnelly/Swifter) を使いましょう。組み込みで Streaming API を叩くメソッドがついています。

おわり