話題の記事

[iOS 11] Social.framework廃止に伴い、アプリにTwitter機能を実装する方法

2017.09.26

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

iOS11からは Social.framework が廃止になることになり、TwitterがiOSで特別扱いされなくなります。 「非推奨」ではなく「即廃止」なので、色々と泣きそうになりますね。

参考: 【iOS 11】Facebook、Twitter、Flickr連携を廃止へ

そこで今までフレームワークを利用してTwitterへの投稿などをしていた部分は変更を余儀なくされるわけですが、 今記事は新しく実装する方法も含めて、アプリにTwitter機能を搭載する方法を書きたいと思います。

準備

Twitterアプリの作成

まず必要なのは「Twitterアプリ」です。 ご存知かと思いますが、アプリはユーザとTwitterアプリを連携させることでTwitterの機能を利用することができます。

Twitterにサインインした状態で Twitterの開発者用ページ に行きます。

[Create New App] で作成画面へ

1

Twitterアプリの名前などそれぞれの必須項目を埋めます。 そのうちの [Callback URL] は https://example.com にします。

2

これでTwitterアプリが作成されます。

詳細ページの [Keys and Access Tokens] > [Applicastion Settings] の [Consumer Key (API Key)] と [Consumer Secret (API Secret)] を実際に使用します。

また、ツイートをさせるためには書き込み権限が必要なので、 [Access Level] が 「Read and write」になっていることも確認しましょう(デフォルトではそうなっているはずですが)。

3

TwitterKitの準備

インストール

Twitterが公式に出している TwitterKit というライブラリをCocoapods経由で取得・使用することになります。

Podfileに

pod 'TwitterKit'

を追加して pod install します

info.plist

info.plist にURLスキームの設定を足してやります。すでに他のスキーム設定がある場合はそこに追加する形になります。

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>twitterkit-{Consumer Key}</string>
    </array>
  </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>twitter</string>
    <string>twitterauth</string>
</array>

twitterkit-XXXXXXXX には先程作ったTwitterアプリの ConsumerKey を付けます。 例えばtwitterkit-RpmNZTabcd1234abcd1234のような形です。

追記すると info.plist は下図のような形になり、

4

アプリ設定を見ると下図のようになると思います。

5

ブリッジファイル

ライブラリは objective-c で出来ているので、 swift でのプロジェクトの場合はブリッジしてやらなければいけません。

  1. Xcodeプロジェクトの左ペインで適当な場所(たとえばルートグループ)を選択する。
  2. 上部メニュー [File] > [New] > [File…] からファイル作成ダイアログを出す。
  3. "Objective-C File" を選んで適当な名前(たとえば「Temp」とかでいいです)を付けて進む
  4. ファイルの作成場所を指定したくらいに "Would you like to configure an Objective-C bridging header?" とアラートで聞かれるのでYES
  5. 左ペインに {プロジェクト名}-Bridging-Header.h というファイルが出来たのを確認して、2項目前に作った Objective-C のファイルはプロジェクトから削除(ゴミ箱行き)
  6. Bridging-Header.h の中に以下を追記する
//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
#import <TwitterKit/TwitterKit.h>

すでにブリッジファイルがある場合、最後の作業だけで大丈夫です。

たまにアラートでブリッジファイル作成のことを聞かれないこともあるので、その場合は手動でやっていく手もあります(「Bridging-Header」というキーワードで検索すれば見つかるかと思います)。

AppDelegate

AppDelegate に TwitterKit の初期設定をしてやります。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        Twitter.sharedInstance().start(withConsumerKey: "(Consumer Key)", consumerSecret: "(Consumer Secret)")
        return true
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        if Twitter.sharedInstance().application(app, open: url, options: options) {
            return true
        }
        return false
    }
}

基本的にTwitterクラスは sharedInstance() でシングルトンオブジェクトを呼び出して、それに対して処理を指示していく形になります。

application(_:didFinishLaunchingWithOptions:) では、「作ったTwitterアプリを使うよ」ということを指示しています。ここでTwitterアプリの ConsumerKey、ConsumerKeySecret の情報を渡してあげます。

application(_:open:options:) では、サインイン時の外部アプリとのやりとりを指示するのですが、その内容はライブラリに丸投げするので、上記コードのよう実装してやるだけで大丈夫です。

もっともシンプルな実装

準備が終われば TwitterKit を使ってTwitterの機能を使うことができます。

ユーザに「Twitterにログインさせて、何かツイートをさせるコンポーザを表示して、実際にツイートをしてもらう」という機能を実装するために必要なソースコードは

TWTRComposer().show(from: self) { _ in }

だけになります。(selfにはビューコントローラが入る)

これだけで

  • Twitterにログインしているかどうかの判定
  • Twitterへのログインをさせる
  • Twitterアプリとユーザを連携させる
  • ツイートを書くためのユーザインターフェイス(コンポーザ = 下図)を表示する
  • ツイート投稿する
  • 失敗があればアラートを表示する

までをすべてやってくれます。

7

初期値を決めたり、コンポーザの処理が終わったときの動きを作ったりする場合でも、下記のソースのようにしてやるだけでありません。

let composer = TWTRComposer()
composer.setText("ツイッターのテストだぽよ")
composer.show(from: self) { result in
    // 終わったら何かやる
}

画像をツイートに含めたい場合は composer.setImage() など、他にも色々とあります。

ログイン管理

何もかもを自動的にやってくれるコンポーザの仕組みですが、実装は楽な分だけ自由度は損なわれます。ツイート投稿以外のAPIを叩きたいこともありますし、ツイート投稿をコンポーザ以外で行いたいこともあります。その場合はログイン状況などを自前で管理してやる必要がありますが、これもそこまで難しい話ではありません。

ログインしているかどうか

ログイン状況は sessionStore にて管理されます。 session()メソッドでは最後にログインしているユーザの認証セッション情報(TWTRAuthSession)を取得できます。ログインをしていない状況ならば nil が返るのでユーザ存在の判定ができます。

if let session = Twitter.sharedInstance().sessionStore.session() {
    print(session.userID)
} else {
    print("アカウントはありません")
}

複数のアカウントを管理する場合は、

// UserIDを指定してセッションを取得
Twitter.sharedInstance().sessionStore.session(forUserID: session.userID)

// 過去にログインしたセッションを配列で取得
// [Any]が戻り値だが、中身は[TWTRAuthSession]
Twitter.sharedInstance().sessionStore.existingUserSessions()

を使用することになるでしょう。

ログインする

ユーザにログインさせるのも実装は簡単です。下記のように実装します。

Twitter.sharedInstance().logIn { session, error in
    guard let session = session else {
        if let error = error {
            print("エラーが起きました => \(error.localizedDescription)")
        }
        return
    }
    print("@\(session.userName)でログインしました")
}

こうすると自動的に下図のような画面がモーダル表示され、あとはよしなにやってくれます。

6

ログアウトする

現在ログイン中のアカウントのログアウトはこのような感じです

if let session = Twitter.sharedInstance().sessionStore.session() {
    Twitter.sharedInstance().sessionStore.logOutUserID(session.userID)
}

TwitterAPIをキックする

Twitterが用意する各APIを実行するには、TWTRAPIClient というクラスを使用します。 どのアカウント(認証セッション)を使用するかを最初に渡せば、あとはリクエストを作って投げてやるだけです。

Twitterでよくある処理の2例をご紹介します

ツイートを投稿する

投稿は書き込む処理なので POST になります。

var clientError: NSError?

let apiClient = TWTRAPIClient(userID: session.userID)
let request = apiClient.urlRequest(
    withMethod: "POST",
    url: "https://api.twitter.com/1.1/statuses/update.json",
    parameters: [
        "status": "ツイッターのテストだぽよ",
    ],
    error: &clientError
)

apiClient.sendTwitterRequest(request) { response, data, error in // NSURLResponse?, NSData?, NSError?
    if let error = error {
        print(error.localizedDescription)
    }
    // 投稿後の処理など
}

タイムラインを取得する

こちらは GET での取得になります。正常にいけば data にはJSON文字列のバイナリが返ってきますので、それを適宜エンコードしてやればいいかと思います。

こちらのサンプルは「自分のタイムラインから10件取得してくる」処理になります。

var clientError: NSError?

let apiClient = TWTRAPIClient(userID: session.userID)
let request = apiClient.urlRequest(
    withMethod: "GET",
    url: "https://api.twitter.com/1.1/statuses/user_timeline.json",
    parameters: [
        "user_id": session.userID,
        "count": "10", // Intで10を渡すとエラーになる模様で、文字列にしてやる必要がある
    ],
    error: &clientError
)

apiClient.sendTwitterRequest(request) { response, data, error in // NSURLResponse?, NSData?, NSError?
    if let error = error {
        print(error.localizedDescription)
    } else if let data = data, let json = String(data: data, encoding: .utf8) {
        print(json)
    }
}

まとめ

ソーシャルフレームワークの廃止により、Twitterは優しくマイグレーションの方法を解説してくれています。 フレームワークをがっつり使っていると移行が面倒くさそうに思えますが、実際の実装は以前とあまり大きな変更もなく行けそうです。

参考

Migrating from iOS Social Framework