クラスを使ってツイッターAPIのモジュールを作ろう

##Classの解説とメリット

ここからは、Classを使ってTwitterサービスモジュールを作っていきます。
今までもViewControllerやUIパーツなどで、自然と使ってきましたが今回はこのクラスを使ってTwitterAPIを使うためのモジュールを作成していきます。

Swiftのクラスの特徴として、C++やObjective-Cのようにヘッダーファイルを分ける必要がありません。全て１つのファイルに書くことができます。また、クラスはプロパティを持つことができます。クラスにプロパティを持たせることによって、必要な時にデータをわざわざ維持したり取得したりすることを減らせます。

![Screen Shot 2015-09-05 at 3.09.11 AM.png](https://qiita-image-store.s3.amazonaws.com/0/35442/90a430e2-d05d-34bc-1eed-318f01e8534d.png)


なぜモジュール化するかというと、今までは各画面で同じFrameworkを読み込んだりユーザーデータを受け渡したりする必要があり、新しいビュークラスを実装するたびに同じものを使うために同じような実装をすることが多々ありました。

モジュール化することで各ビューで同じ実装をしなくても、モジュールを読み込むことでほとんど実装なく同様にAPIを利用することができるようになり、コード量もオーバーヘッドも減らすことができます。


##Classを使った開発アプローチと実装

では、モジュールを実装していきます。

![Screen Shot 2015-09-05 at 2.37.37 AM.png](https://qiita-image-store.s3.amazonaws.com/0/35442/2a2d3848-e1c8-75d9-021a-b8b022983e2c.png)


```swift
import UIKit
import Accounts
import Social

class TwitterServiceManager: NSObject {
    var accountStore = ACAccountStore()
    var twAccount = ACAccount?()
    var accounts:[ACAccount]?
    var tweets = []

    func initWithId(id:Int) {
        setId(id);
    }
    
    func setId(id:Int)
    {
        NSUserDefaults.standardUserDefaults().setInteger(id, forKey: "TwitterUserListIndex")
    }
    
    func myId() -> Int
    {
        return NSUserDefaults.standardUserDefaults().objectForKey("TwitterUserListIndex")!.integerValue
    }
    
    func myAccount() -> ACAccount
    {
        return accountList()[myId()]
    }

    func accountList() -> [ACAccount]
    {
        return accounts!
    }

    //  Twitter APIを使ってタイムラインを取得しtweetsに保存する
    func fetchTimeline(completion:(success:Bool) -> Void)
    {
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
        let URL = NSURL(string: "https://api.twitter.com/1.1/statuses/home_timeline.json")

        let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .GET, URL: URL, parameters: nil)
        request.account = twAccount

        UIApplication.sharedApplication().networkActivityIndicatorVisible = true

        request.performRequestWithHandler { (data, response, error:NSError?) -> Void in
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false

            if error != nil {
                println("Fetching Error: \(error)")
                completion(success: false)
                return
            }

            var tweetResponse: AnyObject? =  NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments, error: nil)

            if let tweetDict = tweetResponse as? Dictionary<String, AnyObject>{
                completion(success: false)
                return
            }

            self.tweets = tweetResponse as! NSArray
            completion(success: true)
        }
    }

    func fetchAccountsList(completion:(success:Bool) -> Void)
    {

        let accountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter)
        accountStore.requestAccessToAccountsWithType(accountType, options: nil) { (granted:Bool, aError:NSError?) -> Void in
            
            if let error = aError {
                println("Error! - \(error)")
                completion(success: false)
                return;
            }
            
            if !granted {
                println("Cannot access to account data")
                completion(success: false)
                return;
            }

            self.accounts = (self.accountStore.accountsWithAccountType(accountType) as? [ACAccount])!
            completion(success: true)
        }
    }

    func sendTweet(tweet:String, completion:(success:Bool) -> Void)
    {
        let URL = NSURL(string: "https://api.twitter.com/1.1/statuses/update.json")

        if count(tweet) <= 0 {
//            var alert = UIAlertController(title: "Error", message: "Please input text", preferredStyle: UIAlertControllerStyle.Alert)
//            alert.addAction(UIAlertAction(title: "OK", style: .Default, handler:nil))
//            self.presentViewController(alert, animated: true, completion:nil)
            completion(success: false)
            return
        }

        var params = ["status": tweet]

        // リクエストを生成
        let request = SLRequest(forServiceType: SLServiceTypeTwitter,
            requestMethod: .POST,
            URL: URL,
            parameters: params)

        // 取得したアカウントをセット
        request.account = twAccount

        // APIコールを実行
        request.performRequestWithHandler { (responseData, urlResponse, error) -> Void in

            if error != nil {
                println("error is \(error)")
                completion(success: false)
            }
            else {
                // 結果の表示
                let result = NSJSONSerialization.JSONObjectWithData(responseData, options: .AllowFragments, error: nil) as! NSDictionary
                completion(success: true)
                println("result is \(result)")
            }
        }
    }
}
```


##まとめ

* クラスはUIパーツやViewControllerなどの部品をつくるベースになっている
* クラスを使ってデータをネット通信やデータなどを集約したモジュールを作れる
* データやネットワークのモジュールを作ることでUIやViewControllerの実装をシンプルにできる