はじめに

以前の記事でもTwitterでつぶやくプログラミングを解説しましたが、前回のプログラムでは決められた画面が表示してTwitterでつぶやくしか機能がありませんでした。

  • つぶやく以外にもタイムラインを取得してアプリで表示したい
  • 自分で画面などをデザインしてTwitterのアプリを作りたい
  • Twitterの様々な機能をアプリで利用したい

上記のような場合はTwitter APIを使用してプログラムを行います。

Twitter APIとは?

Twitter API(アプリケーションプログラムインターフェイス)とはTwitterが外部の開発者向けにTwitterの機能をSwiftなどのプログラムから利用できるサービスです。

Swiftの場合はiPhone端末に登録されているTwitterアカウントを利用してTwitter APIを利用することができます。

まずはTwiiterの機能を利用する前にTwitterアカウント取得を行います。

 

Twitterアカウント取得を行う

Twitterアカウントの一覧を取得する

まずはプロジェクト名を「TwitterAPISample」あたりの名前にしてプロジェクトを作成しTextViewとButtonを配置し、下図のようにButtonのTextを「Tweet」に設定、TextViewのTextを「これはつぶやきのテストです。」設定してTextViewの背景色をわかりやすいように変更しましょう。

スクリーンショット_2015-12-10_19_11_13

 

TextViewとButtonを配置したら、下図のようにTextViewのアウトレットとButtonのアクションを作成しましょう。

スクリーンショット_2015-12-10_19_16_17

プロジェクト作成、オブジェクト配置の方法がわからない場合は以下を参考にしてください。

Xcodeの基本的な開発の流れ – Xcodeの使い方1

 

「ViewController.swift」を開いてTwitterアカウントを取得するプログラムを記述しましょう!ViewController.swiftの上の部分にTwitterアカウント認証を行うには「Accounts」をTwitterの機能を利用するには「Social」をインポートします。

import UIKit
import Accounts //Twitterアカウント認証する場合にインポートします
import Social //Twitterの各機能を利用する場合にインポートします

 

 

Twiiterアカウント認証を行う「ACAccountStore」クラスの変数と、Twitterアカウント情報を保持する「ACAccount」クラスの変数を「ViewController」クラスの上の部分に宣言しましょう。

class ViewController: UIViewController {
    @IBOutlet weak var myTextView: UITextView!
 
    var accountStore = ACAccountStore() //Twitter、Facebookなどの認証を行うクラス
    var twitterAccount: ACAccount? //Twitterのアカウントデータを格納する

    …
}

 

 

いよいよTwitterアカウントの認証をプログラミングしていきましょう!「getTwitterAccount」という名前の関数を作成しプログラムの処理を以下のように記述します。この関数をviewDidLoadから呼び出します。

    //Twitterのアカウント認証を行う
    private func getTwitterAccount() {

        //アカウントを取得するタイプをTwitterに設定する
        let accountType =
            accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)

        //Twitterのアカウントを取得する
        accountStore.requestAccessToAccountsWithType(accountType, options: nil)
        { (granted:Bool, error:NSError?) -> Void in
                
            if error != nil {
                // エラー処理
                print("error! \(error)")
                return
            }
                
            if !granted {
                print("error! Twitterアカウントの利用が許可されていません")
                return
            }
            
            // Twitterアカウント情報を取得
            let accounts = self.accountStore.accountsWithAccountType(accountType)
                as! [ACAccount]

            if accounts.count == 0 {
                print("error! 設定画面からアカウントを設定してください")
                return
            }
            
            // ActionSheetを表示
            self.selectTwitterAccount(accounts)
        }
    }

 

 

上記のプログラミングについて詳しく解説していきます。定数「accountType」を定義してTwitterのアカウントを取得するように設定しています。

「ACAccountStore」クラスの変数「accountStore」の「accountTypeWithAccountTypeIdentifier」の引数に定数「ACAccountTypeIdentifierTwitter」を指定することによりTwitterのアカウントを取得できます。

//アカウントを取得するタイプをTwitterに設定する
let accountType =
    accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)

 

ここでTwitterのアカウント取得処理が行われます。引数に上記で設定した定数「accountType」を指定します。optionは特に設定しないでnilを指定しています。

//Twitterのアカウントを取得する
accountStore.requestAccessToAccountsWithType(accountType, options: nil)

 

ここの部分はTwitterアカウント取得処理が終了した時に実行されます。Twitterアカウント取得処理が成功したのか?失敗したのか?その情報が変数「granted」と変数「error」に格納されています。

{ (granted:Bool, error:NSError?) -> Void in
                
    if error != nil {
        // エラー処理
        print("error! \(error)")
        return
    }
                
    if !granted {
        print("error! Twitterアカウントの利用が許可されていません")
        return
    }
            
    // Twitterアカウント情報を取得
    let accounts = self.accountStore.accountsWithAccountType(accountType)
        as! [ACAccount]

    if accounts.count == 0 {
        print("error! 設定画面からアカウントを設定してください")
        return
    }
            
    // ActionSheetを表示
    self.selectTwitterAccount(accounts)
}

 

Twitterアカウント取得終了処理のプログラムを細かく見てみましょう!

まずは変数「error」に何らかの内容が格納されているか確認しています。変数「error」に内容が格納されている場合は、何らかの理由でTwitterアカウント取得処理に失敗したので、エラー内容をデバッグエリアに出力して処理を中断します。

if error != nil {
    // エラー処理
    print("error! \(error)")
    return
}

 

Twitterアカウント取得処理を最初に実行した時は以下の画面が表示されます。

スクリーンショット 2015-12-11 15.57.41

上図で「OK」を選択すると変数「granted」がtrueに設定され、「許可しない」を選択すると変数「granted」がfalseに設定されます。以下の部分は変数「granted」がfalseの場合はデバッグエリアにメッセージを出力して処理を中断します。

if !granted {
    print("error! Twitterアカウントの利用が許可されていません")
    return
}

プログラム実行時に「許可しない」を選択してしまった場合はシミュレータの「設定」→「プライバシー」→「Twitter」から許可してください。

実際にiPhoneアプリを開発する場合は「下図の設定を行ってください」という旨のエラーメッセージをわかりやすく表示してiPhoneアプリを利用するユーザに許可してもらう必要があります。

Simulator Screen Shot 2015.12.11 16.05.16

 

Twitterアカウント取得処理で問題がないことを確認してからTwitterアカウント情報を取得しています。

Twitterのアカウントは複数のアカウントをiPhone端末に登録することができるので、iPhone端末に登録されているアカウント数を確認してiPhone端末にTwitterアカウントが登録されていない(0件)の場合は処理を中断します。

// Twitterアカウント情報を取得
let accounts = self.accountStore.accountsWithAccountType(accountType)
    as! [ACAccount]
if accounts.count == 0 {
    print("error! 設定画面からアカウントを設定してください")
    return
}

プログラム実行時はシミュレータにTwitterアカウントは登録されていないので「設定」→「Twitter」からTwitterアカウントを登録してください。

Simulator Screen Shot 2015.12.11 16.21.46

 

取得したTwitterアカウント一覧から使用するTwitterアカウントを選択する

前述しましたがiPhone端末にはTwitterアカウントは複数登録できるため、ユーザに利用するTwitterアカウントを選択させる必要があります。

ユーザーにTwitterアカウントを選択させる方法はいろいろな方法がありますが、今回は関数「selectTwitterAccount」を作成して、ActionSheetにTwitterアカウント一覧を表示してユーザに選択させます。

ちなみにiPhoneのTwitterクライアントはTableViewを利用してTwitterアカウントを選択されていることが多いですね。

image

 

// ActionSheetを表示
self.selectTwitterAccount(accounts)
private func selectTwitterAccount(accounts: [ACAccount]) {
    
    // ActionSheetのタイトルとメッセージを設定する
    let alert = UIAlertController(title: "Twitter",
        message: "アカウントを選択してください",
        preferredStyle: .ActionSheet)
        
    // アカウント選択のActionSheetを表示するボタン
    for account in accounts {
        alert.addAction(UIAlertAction(title: account.username, style: .Default,
            handler: { (action) -> Void in

                // 選択したTwitterアカウントのデータを変数に格納する
                print("your select account is \(account)")
                self.twitterAccount = account
        }))
    }
        
    // 表示する
    self.presentViewController(alert, animated: true, completion: nil)
}

 

関数「selectTwitterAccount」の内容を見てみましょう!まずActionSheetのタイトルとメッセージを設定します。

// ActionSheetのタイトルとメッセージを設定する
let alert = UIAlertController(title: "Twitter",
    message: "アカウントを選択してください",
    preferredStyle: .ActionSheet)

 

関数「selectTwitterAccount」の引数accountsにTwitterアカウントの一覧が格納されているので、for文で変数「account」に1つずつTwitterアカウントの情報を格納してActionSheetの項目に追加しています。

「handler: { (action) -> Void in … } 」の部分にActionSheetの項目が選択された時の処理を記述します。ここでは選択されたTwitterアカウントのデータを変数「twitterAccount」に格納しています。

// アカウント選択のActionSheetを表示するボタン
for account in accounts {
    alert.addAction(UIAlertAction(title: account.username, style: .Default,
    handler: { (action) -> Void in
    // 選択したTwitterアカウントのデータを変数に格納する
    print("your select account is \(account)")
    self.twitterAccount = account
    }))
}

 

最後に設定したActionSheetを表示します。これでようやくTwitterアカウント取得ができます〜

// 表示する
self.presentViewController(alert, animated: true, completion: nil)

Simulator Screen Shot 2015.12.11 17.23.48

 

まとめ

ツイートするプログラムまで解説すると長くなりそうなので今回はここまで!次回、Twitterでツイートするプログラムを解説します。

Twitter APIを利用してつぶやく(その2) – 実践!Swiftプログラミング4

参考にTwitterアカウント取得とツイートする全プログラムを以下に記述します。

「ViewController.swift」

import UIKit
import Accounts     //Twitterアカウント認証する場合にインポートします
import Social       //Twitterの各機能を利用する場合にインポートします

class ViewController: UIViewController {
    
    @IBOutlet weak var myTextView: UITextView!

    var accountStore = ACAccountStore() //Twitter、Facebookなどの認証を行うクラス
    var twitterAccount: ACAccount?      //Twitterのアカウントデータを格納する
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //アプリ実行時にTwitter認証を行うアカウントデータを取得する
        getTwitterAccount()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    //Button押下時にTwitterに投稿する
    @IBAction func TouchTweet(sender: AnyObject) {
        postTweet()
    }

    
    //Twitterのアカウント認証を行う
    private func getTwitterAccount() {

        //アカウントを取得するタイプをTwitterに設定する
        let accountType =
            accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)

        //Twitterのアカウントを取得する
        accountStore.requestAccessToAccountsWithType(accountType, options: nil)
        { (granted:Bool, error:NSError?) -> Void in
                
            if error != nil {
                // エラー処理
                print("error! \(error)")
                return
            }
                
            if !granted {
                print("error! Twitterアカウントの利用が許可されていません")
                return
            }
            
            // Twitterアカウント情報を取得
            let accounts = self.accountStore.accountsWithAccountType(accountType)
                as! [ACAccount]

            if accounts.count == 0 {
                print("error! 設定画面からアカウントを設定してください")
                return
            }
            
            // ActionSheetを表示
            self.selectTwitterAccount(accounts)
        }
    }
    
    private func selectTwitterAccount(accounts: [ACAccount]) {
        
        // ActionSheetのタイトルとメッセージを設定する
        let alert = UIAlertController(title: "Twitter",
            message: "アカウントを選択してください",
            preferredStyle: .ActionSheet)
        
        // アカウント選択のActionSheetを表示するボタン
        for account in accounts {
            alert.addAction(UIAlertAction(title: account.username, style: .Default,
                handler: { (action) -> Void in

                    // 選択したTwitterアカウントのデータを変数に格納する
                    print("your select account is \(account)")
                    self.twitterAccount = account
            }))
        }
        
        // 表示する
        self.presentViewController(alert, animated: true, completion: nil)
    }

    // ツイートを投稿
    private func postTweet() {

        let URL = NSURL(string: "https://api.twitter.com/1.1/statuses/update.json")
        
        // ツイートしたい文章をセット
        let params = ["status" : myTextView.text]
        
        // リクエストを生成
        let request = SLRequest(forServiceType: SLServiceTypeTwitter,
            requestMethod: .POST,
            URL: URL,
            parameters: params)
        
        // 取得したアカウントをセット
        request.account = twitterAccount
        
        // APIコールを実行
        request.performRequestWithHandler { (responseData, urlResponse, error) -> Void in
            
            if error != nil {
                print("error is \(error)")
            }
            else {
                // 結果の表示
                do {
                    let result = try NSJSONSerialization.JSONObjectWithData(responseData,
                    options: .AllowFragments) as! NSDictionary
                    
                    print("result is \(result)")

                } catch {
                    return
                }
            }
        }
    }
}

 

参考サイト

iOSアプリでTwitterのタイムライン取得・ツイート投稿を行う(Accounts.frameworkとSocial.rameworkを使って)

Swift 2を使うとNSJSONSerialization.JSONObjectWithData()でコンパイルエラー ‘Extra argument ‘error’ in call’ が発生する

[Swift] クロージャを利用したコールバックの書き方メモ

 

参考書籍