iOS11向けにSocial.frameworkを使わないTwitter投稿

  • 40
    いいね
  • 2
    コメント

基本的にTwitter公式にある情報です。
この記事を読むよりも公式の情報をちゃんと読んだ方がいいと思います。

■ Migrating from iOS Social Framework
https://dev.twitter.com/twitterkit/ios/migrate-social-framework

以下は日本語が読みたい人向けに。 (※17/6/26の内容を元にしています)

6/27 追記
説明の中で使用されているTwitter Kit v3.0はiOS9+をサポート条件にしています。
そのため、アプリのサポートバージョンをiOS9以降に更新してから利用しましょう。
https://dev.twitter.com/twitterkit/ios/upgrading

概要

例年なら9月上旬くらいには公開されるiOS11からはSocial.frameworkを通じてTwitterを利用できなくなります。
その代わりに、TwitterKit3を利用してツイートやユーザーのログイン、TwitterAPIを使用します。

TwitterKit3

インストールページからダウンロードすることもできますが、私はとりあえずCocoaPodsでやります。

Podfile
pod 'TwitterKit'

アプリケーションの登録

開発者用に利用するTwitterアカウントで電話番号の認証を済ませた上で、
Twitterアプリのダッシュボードからアプリケーションを作成します。

  1. 読み書き可能なアプリケーションで作成(Access level: Read and write)
  2. 互換性のため、コールバックURLを設定。使用するつもりがないならhttps://example.comでも設定しておけと書いてある。
  3. SettingsからAllow this application to be used to Sign in with Twitterにチェックを入れる

TwitterKitの初期化処理を設定

URLスキームの追加

info.plist
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>twitterkit-{yourConsumerKey}</string>
    </array>
  </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>twitter</string>
    <string>twitterauth</string>
</array>

6/29 追記
上記の設定を行なっていても、以下のようなエラーが出力されることがあります。

Terminating app due to uncaught exception 'TWTRInvalidInitializationException', 
reason: 'Attempt made to Log in or Like a Tweet without a valid Twitter Kit URL Scheme set up in the app settings. 
Please see https://dev.twitter.com/twitterkit/ios/installation for more info.'

原因はTwitterKitの不具合で、CFBundleURLSchemesの先頭に追加しないと判定されないようです。(v3.0.3時点)
https://twittercommunity.com/t/twitterkit-v3-causes-exception-upon-sign-in-on-ios/88143/7

AppDelegateにハンドラを追加

appDelegate.swift
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
  if Twitter.sharedInstance().application(app, open: url, options: options) {
    return true
  }
  // Your other open URL handlers follow […]
}

Twitter.startを呼ぶ

appDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  Twitter.sharedInstance().start(withConsumerKey: "example-hPpFPVQ64pThkM0", consumerSecret: "exmaple-ovAqziZzzHpU5F163Qg9mj")
  return true
}

Twitterでログイン

 ACAccountStore.requestAccessToAccounts -> Twitter.logIn

ACAccountStore
let account = ACAccountStore()
let accountType = account.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)

account.requestAccessToAccounts(with: accountType, options: nil, completion: {(success, error) in
  if success {
    if let twitterAccount = account.accounts(with: accountType).last as? ACAccount {
      print("signed in as \(twitterAccount.userame)");
    }
  }
})

TwitterKitを利用した場合

TwitterKit
Twitter.sharedInstance().logIn(completion: { (session, error) in
  if let sess = session {
    print("signed in as \(sess.userName)");
  } else {
    print("error: \(error.localizedDescription)");
  }
}

ACAccountStore.accounts -> TWTRSessionStore

アプリケーションを認証すると、TwitterKitがセッションを保存します。
ログイン後は、Twitter.sharedInstance().sessionStore.session()を利用すれば現在の認証済みセッションを取得することができます。
アプリにセッションがあるかどうかはTwitter.sharedInstance().sessionStore.hasLoggedInUsers()でテストできます。
https://dev.twitter.com/twitterkit/ios/log-in-with-twitter

ツイートする

TwitterKitを利用してリンク、画像、ビデオの共有が行えます。

SLComposeViewController -> TWTRComposer

SLComposerViewController
if SLComposeViewController.isAvailableForServiceType(SLServiceTypeTwitter) {
  let composer = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
  composer.setInitialText("Hello Twitter!")
  composer.addImage(UIImage(named: "hello"))
  composer.addURL(URL(string: "https://dev.twitter.com"))
  self.presentViewController(socialController, animated: true, completion: nil)
}

TwitterKitではTWTRComposerで同じ機能を提供します。

TWTRComposer
let composer = TWTRComposer()
composer.setText("Hello Twitter!")
composer.setImage(UIImage(named: "hello"))
composer.setUrl(URL(string: "https://dev.twitter.com"))
composer.show(from: self, completion: nil)

ビデオの投稿なども含めたツイートの構成については、TWTRComposeViewControllerに関するドキュメントを参照
https://dev.twitter.com/twitterkit/ios/compose-tweets

TwitterAPIを利用する

上記の手順にしたがってユーザーの承認を更新し、OAuthで署名されたリクエストを使います。

SLRequest -> TWTRAPIClient

SLRequest
let account = ACAccountStore()
let accountType = account.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)

account.requestAccessToAccounts(with: accountType, options: nil, completion: {(success, error) in
    if success {
        if let twitterAccount = account.accounts(with: accountType).last as? ACAccount
       let statusesShowEndpoint = "https://api.twitter.com/1.1/statuses/show.json"
          let params = ["id": "20"]

          let request = SLRequest(forServiceType: SLServiceTypeTwitter,
      requestMethod: SLRequestMethod.GET,
      URL: URL(string: statusesShowEndpoint),
      parameters: params)
           request?.account = twitterAccount
       request?.perform(handler: {(responseData, urlResponse, error) in
                if let err = error {
                    print("Error : \(err.localizedDescription)")
                } else {
                    print("The first Tweet: \(responseData)")
                }
            })
        }
    }
})

TwitterKit

TWTRAPIClient
if let twitterAccountId = Twitter.sharedInstance().sessionStore.session()?.userID {
  let client = TWTRAPIClient(userID: twitterAccountId)
  let statusesShowEndpoint = "https://api.twitter.com/1.1/statuses/show.json"
  let params = ["id": "20"]
  var clientError : NSError?

  let request = client.urlRequest(withMethod: "GET", url: statusesShowEndpoint, parameters: params, error: &clientError)

  client.sendTwitterRequest(request) { (response, responseData, error) -> Void in
    if let err = error {
        print("Error: \(err.localizedDescription)")
    } else {
      print("The first Tweet: \(responseData)")
    }
  }
} else {
  // Not logged in
}

詳しくはやっぱり公式ドキュメント見た方がいいです。