【iOS】TwitterKitじゃなくて「Swifter」でTwitterログインする

新規アプリを作るときは、FirebaseAuthを使ってログインを実装することが多く、FacebookログインやTwitterログインを良く使います。

FacebookのiOS SDKは安定して使いやすいのですが、Twitter公式がかつてメンテナンスしていた**[TwitterKit](https://github.com/twitter-archive/twitter-kit-ios)は安定していなくて、色々バグが多いです。** (2018年10月に公式サポートが終了している)

ということで、今回はiOSでTwitterログインをする際にTwitterKitよりもオススメな**Swifter**を紹介します。

![swifter](https://github.com/mattdonnelly/Swifter/raw/master/swifter_logo.png)

[mattdonnelly/Swifter](https://github.com/mattdonnelly/Swifter)

## インストール

https://hawksnowlog.blogspot.com/2016/09/tweet-with-swifter.html の記事が詳しいです。cocoapodsなどは対応していないので、Embedded Binariesとして追加しましょう。

# SwifterでTwitterログイン

あらかじめTwitter Developerでアプリを作成し、consumerKeyとconsumerSecretを取得しといてください。

```swift:ViewController.swift
import Swifter

let swifter = Swifter(
    consumerKey: "<--Twitter Developerで作ったconsumerKey-->",
    consumerSecret: "<--Twitter Developerで作ったconsumerSecret-->"
)
swifter.authorize(
    withCallback: "<-アプリに帰ってくるためのコールバックURL->",
    presentingFrom: self,
    success: { accessToken, response in
        // このあとaccessToken使うよ
}, failure: { error in
    print(error)
})
```

成功すると、accessTokenが取得できるので、これをこの後使います。（次の章）

safariに飛んでログインした後に戻ってこれるように、AppDelegateには以下にように書きます。

```swift:AppDelegate.swift
import Swifter

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    return Swifter.handleOpenURL(url, callbackURL: "<-アプリに帰ってくるためのコールバックURL->")
}
```

### 追記

Loginする画面のViewControllerを**SFSafariViewControllerDelegate**に準拠させることを忘れずに！準拠させることでアプリ内でsafariが開けます。（準拠しないと外部のsafariに飛んで、**a poor user experience**という理由でアプリがAppleにリジェクトされました）

```swift:ViewController.swift
import SafariServices

class ViewController: UIViewController, SFSafariViewControllerDelegate {

}
```

# accessTokenの使い方

先ほどのauthorizeメソッドで`accessToken`が取得できます。これはStringではなく、`Credential.OAuthAccessToken`というSwifterが作っている型で、いくつかパラメータを持ちます。

今回はここからkeyとsecretを取得します。

```swift:authorizeメソッドのsuccessの中
guard let accessToken = accessToken else {
    return
}
let oAuthToken = accessToken.key
let secret = accessToken.secret
```

### ローカルで使う

例えばローカルでこのままSwifterの機能であるTwitter投稿をしたりしたい場合は、次からログインなしでできるように、この`accessToken.key`と`accessToken.secret`をUserDefaults等に入れておきます。

そしたら次から以下のようにswifterをinitして使えます。

```swift
let swifter = Swifter(
    consumerKey: "<--Twitter Developerで作ったconsumerKey-->",
    consumerSecret: "<--Twitter Developerで作ったconsumerSecret-->",
    oauthToken: oAuthToken, //ローカルに保存していたやつ
    oauthTokenSecret: secret //ローカルに保存していたやつ
)
swifter.postTweet(status: shareText, success: { status in
    
}, failure: { error in
    
})
```

### Firebaseでログインする

FirebaseAuthでログインしたい場合は、FirebaseAuthの`TwitterAuthProvider.credential`を作ってログインできます。

```swift
import Firebase

let credential = TwitterAuthProvider.credential(
    withToken: oAuthToken,
    secret: secret
)
Auth.auth().signIn(with: credential, completion: { (authResult, error) in
    
})
```

[Firebase公式ドキュメント]( https://firebase.google.com/docs/auth/ios/twitter-login?hl=ja )では、twitterKitでこの`authToken`と`secret`を取得していますが、Swifterで取得したものをここに入れればあとは同様の手順でいけます。

# TwitterKitとの違い

TwitterKitはTwitterネイティブアプリがある場合、アプリに飛んで認証しますが、Swifterの場合はアプリがあってもSafariを起動して認証します。

また、TwitterKitのTwitter投稿は専用のViewControllerを出す必要がありますが、Swifterならコードだけで完結します。

以上です。詳しくは、[mattdonnelly/Swifter](https://github.com/mattdonnelly/Swifter)のリポジトリのサンプルコードやReadmeへ。

# 関連リンク
https://firebase.google.com/docs/auth/ios/twitter-login?hl=ja
https://hawksnowlog.blogspot.com/2016/09/tweet-with-swifter.html
https://github.com/mattdonnelly/Swifter