のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

iPhoneApplication FMDBの使い方

皆さんこんにちわ
お元気ですか?私は元気です。

最近失速気味で申し訳ない。記事に書きたいこと、勉強していることは増えているのですが、どうしても時間が取れず;;

さて、本日はFMDBの使い方について
sqliteと呼ばれるDBのアプリケーションが存在するのですが、それをiPhoneの開発時に簡単に使えるライブラリです。

ちなみに私のXcodeのVersionは5(5.2)です。

外部からライブラリを入れるので色々使う時にはライセンスなどの注意が必要です。

FMDB

導入方法

ライブラリを導入

ダウンロードしたFMDBを解凍後、ライブラリを導入する
解凍したフォルダの中にあるsrcを開く、

f:id:tereka:20140415100843p:plain

プロジェクトはこのような感じです。
f:id:tereka:20140415100300p:plain

この中からfmdb.m以外をプロジェクトへドラッグアンドドロップ

f:id:tereka:20140415101023p:plain

Finishを押す。

最後にXcodesqliteのライブラリを導入する

f:id:tereka:20140415101140p:plain

この部分のLinked Frameworks and Librariesの+を押し、libsqlite3.0.dylibを選択しaddを押す。

使用法

データベースの作成・読み込み
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //Documentフォルダの検索
    NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
    NSString *dir   = [paths objectAtIndex:0];
    //file.dbのDBファイルを作る。存在していれば読みこむ
    FMDatabase *db= [FMDatabase databaseWithPath:[dir stringByAppendingPathComponent:@"file.db"]];
    NSString *sql = @"CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT,testname TEXT);";
    [db open];
    [db executeUpdate:sql]; //SQL実行
    [db close];

    return YES;
}

一応、アプリ立ち上がった時に実行するように組んでます。
うん、フォルダを検索して、なければ作る。ただそれだけ。

補足:ヘッダーに
#import "FMDatabase.h"
#import "FMResultSet.h"
を付けてください。

SQLを実行する

INSERT UPDATEを実行
//INSERT文を作る
NSString *insertSQL = @"INSERT INTO test(testname) VALUES (?)";
[db open];
//?に値を入れる配列を作る
NSArray *insertArgument = [[NSArray alloc] initWithObjects:@"test", nil];
//SQLを生成
[db executeUpdate:insertSQL withArgumentsInArray:insertArgument];
[db close];

通常のSQLを生成して、動的に変化させる部分を配列で作っています。
SQLをexecuteUpdateで実行しています。

SELECTを実行
NSString *selectSQL = @"select * from test";
[db open];
//結果を取得
FMResultSet *results = [db executeQuery:selectSQL];
//結果を取り出し
while( [results next] ){
   //テストネームのカラムを取得する
   NSString *testname = [results stringForColumn:@"testname"];
   NSLog(@"%@",testname);
}
[db close];

同じようにSQLを生成していますが、実行するメソッドをexecuteQueryを使用しています。
取得した結果をFMResultSetに格納し、whileにより、一つ一つ処理しています。

参考文献

http://plus.vc/web/6921/

次は何しよう。

iPhone Application 一番下までスクロールしたらTableVIewが増加するプログラム

皆さんこんにちわ
お元気ですか?私は眠いです。

さて、本日はスクロールについてやってみます。

プロジェクトの生成〜Navigation Controllerの配置

まずは、プロジェクトを作ります。
次に最初にあるViewを削除し、TableViewを配置する。
TableViewを選択し、Editor→Embed in →Navigation Controllerを選択。

Prototype Cells
Table View cell の identifierをCellに変更

TableView
新しくファイルを作りクラスはUITableViewを選択
Custom ClassでClassで先ほど作ったファイルのクラス名を選択

そこまで終わると以下のようなイメージになります

f:id:tereka:20140228092955p:plain

さて、コードでも書くか。

ソースコード

ScrollViewController.h

#import <UIKit/UIKit.h>

@interface ScrollViewController : UITableViewController{
    NSArray *TableContents;
    int page;
}

@end

ScrollVIewController.m

#import "ScrollViewController.h"

@interface ScrollViewController ()

@end

@implementation ScrollViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    page = 3;
    TableContents = [self createData];
}

- (NSArray *)createData{
    NSMutableArray *data = [NSMutableArray array];
    
    for(int i = 0; i < page; i++){
        [data addObject:@"神はいわれた。これは世界の全てだ"];
        [data addObject:@"そんな装備で大丈夫か?"];
        [data addObject:@"大丈夫だ問題ない"];
        [data addObject:@"神は言っているここで死ぬ運命ではないと"];
        [data addObject:@"一番いいのを頼む"];
    }
    
    return [data copy];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if(self.tableView.contentOffset.y >= (self.tableView.contentSize.height - self.tableView.bounds.size.height))
    {
        page++;
        TableContents = [self createData];
        [self.tableView reloadData];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return TableContents.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }
    cell.textLabel.text = [TableContents objectAtIndex:indexPath.row];
    return cell;
}

@end

解説

ScrollVIewController.h

TableContents:内容
page:ページ数を設定しています。

ScrollVIewController.m

ViewDidRead

初期化に必要な設定、ページ数と内容の設定を行っています。

createData

データ作っています。

scrollVIewDidScroll

ScrollViewDidScrollメソッドをオーバーライドするのかなぁ…?
なんかこれを実装するとスクロールしたときに呼ばれます。

tableView.ContentOffset.y = 今の表の全体のサイズ(y軸)
tableView.ContentOffset.height =スクロール
tableView.bounds.height = 表示されてるサイズ

だと思う。

まぁ高さ足りなくなったら増強すりゃいいじゃんって発想です。

f:id:tereka:20140228095954p:plain

iPhone Push down refresh、Refresh Controller くるくるまわってロード

皆さんこんにちわ
お元気ですか?私はスリープが嫌いになりました。睡眠じゃないです。PCです。
ええ、nohupが仕事をしなかったのですよ。大量の時間を無駄にしました。
今も動いてたらうれしいなぁ…多分日曜日に終わるか終わらないかだから、勝手に仕事してくれないと困るんです。

さて、本日はリフレッシュ機能について
あの、twitterとかで上にくいってするとくるくるまわって更新するあやつのことです。
Push down refresh とか Refresh Controllerっていうんですね。

今日はそれを実装してみましょう。

StoryBoard

プロジェクトの生成〜Navigation Controllerの配置

まずは、プロジェクトを作ります。
次に最初にあるViewを削除し、TableViewを配置する。
TableViewを選択し、Editor→Embed in →Navigation Controllerを選択。

Prototype Cells

Table View cell の identifierをCellに変更

TableView

新しくファイルを作りクラスはUITableViewを選択
Custom ClassでClassで先ほど作ったファイルのクラス名を選択

Refresh

最後にTable View ControllerのRefreshingをEnabledに変更

そこまで終わると以下のようなイメージになります。

f:id:tereka:20140227210752p:plain

ソースコードを書いていきましょう

ソースコード

RefreshViewController.h

#import <UIKit/UIKit.h>

@interface RefreshViewController : UITableViewController{
    NSArray* StringArray;
}

@end

RefreshViewController.m

#import "RefreshViewController.h"

@interface RefreshViewController ()

@end

@implementation RefreshViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    StringArray = [[NSArray alloc] initWithObjects:@"東京",@"大阪", nil];
    [self.refreshControl addTarget:self action:@selector(updateRecords) forControlEvents:UIControlEventValueChanged];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return StringArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
   if (!cell) {
       cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
   }
    cell.textLabel.text = [StringArray objectAtIndex:indexPath.row];
    return cell;
}

-(void)updateRecords{
    StringArray = [[NSArray alloc] initWithObjects:@"関東",@"関西", nil];
    [self.tableView reloadData];
    [self.refreshControl endRefreshing];
}

@end

解説

RefreshController.h

NSArrayを宣言しているだけです

RefreshController.m

ViewDidLoad

StringArrayはテーブルの要素を入れているのみです。

refreshcontrolの部分が新しいですね。
refreshcontrolで、イベントを動作をリンクさせています。
今回のメンバ関数の内容を動作として記載すると、

UIControlEventValueChangedは値が変化したときなので、refreshControlの値が変更されたときにupdateRecordsを呼び出す

ような動作を行っていると思います。厳密には違いそうですが、、、。

イベントコントロールについてはこちらに記載されていました。
http://iphone-tora.sakura.ne.jp/uicontrol.html

numberOfSectionsInTableView,numberOfRowsINSection,cellForRowAtIndexPath

相変わらずの処理ですね。セルに内容を入れてテーブルを作っています。

updateRecords

self.tableView reloadData = 新しくテーブルを作っているだけです。
self.refreshControl endRefreshing =ここで更新作業は終わりですよ。(くるくるもここで終了)

動作

こんな表示から
f:id:tereka:20140228011239p:plain

くるくるまわって

f:id:tereka:20140228011333p:plain

できあがり、文字変わりましたよね!

f:id:tereka:20140228011347p:plain

iPhone CustomCellを作る。

皆さんこんばんわ
お元気ですか。私はC++Makefileや便利ツールを聞いて色々と死にそうです。
ファイルの分割方法がよくわかりません。

これはいつか実験して学習するとしましょう。

さて、今回はCutomCellです。表の中をLabel2つにしたい!とか画像入れたい!とかそんなニーズにお答えするセルを作るのがこれです。
まぁセルの中にも色々突っ込んで修正したいわけです。自由がいいんです自由が

さぁいくぞ

プロジェクトの生成、Storyboardの編集

プロジェクト名:CustomCellTest

などなど

とりあえず、画面はこんな感じになります。

f:id:tereka:20140225213206p:plain

その上で、ラベルを追加します。

f:id:tereka:20140225213715p:plain

Viewのタグをそれぞれ1,2と設定します。

ソースコード周り

ファイルを生成します。ObjectiveC-classで大丈夫です。
CustomCell を UITableViewCell
TableView を UITableViewController
として生成してください。

PrototypeCellsのClassにCustomCellをC登録する。

f:id:tereka:20140225233233p:plain

CustomCellにLabelなどを定義する。
定義の仕方はCustomCell.hへLabelなどをcontrolで引っ張って繋ぐ。

f:id:tereka:20140225233022p:plain

最後にidentifierをCellとして登録

f:id:tereka:20140225233434p:plain

ソースコード

CustomCell.h

#import <UIKit/UIKit.h>

@interface CustomCell : UITableViewCell
@property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
@property (strong, nonatomic) IBOutlet UILabel *DescriptionLabel;

@end

Labelなどを紐で繋ぐだけ。

CustomCell.m

こちらは何も弄っていません。最初に生成された通りです。

#import "CustomCell.h"

@implementation CustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

@end

TableView.h

#import <UIKit/UIKit.h>
#import "CustomCell.h"

@interface TableView : UITableViewController{
    NSArray *TableArray;
    NSArray *DescriptionArray;
}
@property (strong, nonatomic) IBOutlet UITableView *myTableView;

テーブルに入れる内容をインスタンス変数として定義する。

TableView.m

#import "TableView.h"
#import "CustomCell.h"

@interface TableView ()

@end

@implementation TableView

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
     TableArray = [[NSArray alloc] initWithObjects:@"YAS",@"AS",@"Nis", nil];
     DescriptionArray = [[NSArray alloc] initWithObjects:@"ssS",@"AsS",@"Nis", nil];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;
 
    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return TableArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    if(!cell){
        cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    cell.TitleLabel.text = [TableArray objectAtIndex:indexPath.row];
    cell.DescriptionLabel.text = [DescriptionArray objectAtIndex:indexPath.row];
    // Configure the cell...
    
    return cell;
}
ViewDidLoad

変数の内容を定義するのみ

numberOfSectionsInTableView

1でおkです。

numberOfRowsInSection

表の長さ

cellForRowAtIndexPath

表の列を確保し、cellの中身があれば、再利用する。
そして、NSArrayで定義した内容をLabelに入れる。

ただ、それだけです。

iPhone Application Twitterクライアントを作ろう

皆さんこんにちわ。
お元気ですか。私は眠いです。

今日はiPhone ApplicationでTwitterクライアントを作ってみようと思います。
Xcodeのインストールは割愛します。

プロジェクトの作成

まずは、新しいプロジェクトを生成します。今回はSingleViewApplicationを選択

f:id:tereka:20140225083301p:plain

ProjectNameに適当な内容を追加、今回はTwitterApplicationとしました。

f:id:tereka:20140225093358p:plain

適当なフォルダでCreateを実行

f:id:tereka:20140225083319p:plain

StoryBoard

画面を作成

次にstoryboardで画面を構築します。Main_iPhone.storyboardを選択。
最初は以下のようになっていると思います。

f:id:tereka:20140225083701p:plain

早速ViewControllerを削除し、TableViewを追加

f:id:tereka:20140225085621p:plain

Table View Controllerを選択して、タブからEditor→Embed in →Navigation Controllerを選択

f:id:tereka:20140225084943p:plain

投稿ボタンを追加

次に投稿ボタンを作ってみましょう。まずは、ボタンを置く。

f:id:tereka:20140225085800p:plain

そしてプロパティにて変更する。identifierをComposeに

f:id:tereka:20140225090003p:plain

ファイルとViewの紐付け

新しくファイルを作ります。このファイルに先ほど生成したTable Viewの実装を記入します。
Objective-C classを選択し、名前は適当に作ります。今回はTwitterViewControllerとしました。

f:id:tereka:20140225090426p:plain

しかし、現在、TableViewとこのTwitterViewControllerが紐づいていません。
紐づけましょう。Main_iPhone.storyboardを開き、TableViewをクリック
Custom Classのタブを選択し、TwitterViewControllerを選択

f:id:tereka:20140225090857p:plain

これで紐付けができました。

投稿ボタン実装編

ボタンはまだ紐づいていません。まずは、ボタンを押した時に実行するメソッドを登録しましょう。
TwitterViewController.hを開きましょう。

その上で、ボタンをクリックし、コントロールを押しながらファイルに線をのばすと画面が表れます。
ConnectionはActionを選択し、名前をTwitterButtonとしました。

f:id:tereka:20140225093610p:plain

するとコードも変化し、以下のようになっていると思います。

#import <UIKit/UIKit.h>

@interface TwitterViewController : UITableViewController
- (IBAction)TwitterButton:(id)sender;

@end

これでメソッドを登録することができました。
さて、ボタンのメソッドの本体を書きましょう。

今度はTwitterViewController.mを開きます。
最後の方に

- (IBAction)TwitterButton:(id)sender {
}

が追加されているので、この中に書きます。

ヘッダーにを追加して

以下のように変更してください。

#import <Social/Social.h>

(略)

- (IBAction)TwitterButton:(id)sender {
    SLComposeViewController *twitterPostVC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
    [twitterPostVC setInitialText:@"てすと"];
    [self presentViewController:twitterPostVC animated:YES completion:nil];
}

1行目でTwitterの画面を生成し、2行目でテキストを突っ込み、3行目で呼び出しているだけです。
まぁSocialのメソッドなりクラスが勝手に画面を作ってくれます。便利です。
Runしてボタンをクリックして以下のような画面が出れば成功です。

f:id:tereka:20140225094655p:plain

タイムラインの表示

さて、後はコードを書くだけです。

viewDidLoad

- (void)viewDidLoad
{
    [super viewDidLoad];
    //最近、APIが変更になったのでurlは気をつけましょう。
    NSString *apiURL = @"https://api.twitter.com/1.1/statuses/home_timeline.json";
    
    ACAccountStore *store = [[ACAccountStore alloc] init];
    ACAccountType *twitterAccountType =
    [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
    
    [store requestAccessToAccountsWithType:twitterAccountType options:nil completion:^(BOOL granted,NSError *error){
        if(!granted){
            NSLog(@"Twitterの認証を拒否");
        }else{
            NSArray *twitterAccounts = [store accountsWithAccountType:twitterAccountType];
            if ([twitterAccounts count] > 0) {
                ACAccount *account = [twitterAccounts objectAtIndex:0];
                NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
                [params setObject:@"1" forKey:@"include_entities"];
                
                NSURL *url = [NSURL URLWithString:apiURL];
                SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                                        requestMethod:SLRequestMethodGET
                                                                  URL:url parameters:params];
                [request setAccount:account];
                [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
                [request performRequestWithHandler:^(NSData *responseData,NSHTTPURLResponse *urlResponse,NSError *error) {
                    if(!responseData){
                        NSLog(@"response error: %@", error);
                    }else{
                        NSError *jsonError;
                        tweets = [NSJSONSerialization JSONObjectWithData:responseData
                                                                 options: NSJSONReadingMutableLeaves error:&jsonError];
                        if(tweets){
                            dispatch_async(dispatch_get_main_queue(), ^{ // 追加
                                [self.tableView reloadData]; // 追加
                            });
                        }else{
                            NSLog(@"%@", error);
                        }
                    }
                }];
            }
        }
    }];

viewDidLoadメソッドはページ実行時に実行されるメソッドです。
ポイントをいくつかご紹介します。

apiURL

apiURL 今年にTwitterのプロトコルが変更され、httpからhttpsに変更されました。その都合でいくつかのブログのurlでapi動作しないことがあります、気をつけましょう。

requestAccessToAccountsWithType

認証を要求する箇所。
grantedの中にTrue or Falseが入っている。

SLRequest

APIをたたくクラス、Oathなどをスルーしてくれるそうです。

NSJSONSerialization

返ってきたデータを変換する。

dispatch_async

同期的に実行する為のメソッド

self.tableView reloadData

データをリロードする。テーブルを再描写

numberOfSectionsInTableView

繰り返しのセルの数

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

numberOfRowsInSection

行数を突っ込めば大丈夫です。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [tweets count];
}

cellForRowAtIndexPath

セルの内容を決めるメソッドです。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    // Configure the cell...
    if(cell == nil){ 
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    } 

    NSDictionary *status = [tweets objectAtIndex:indexPath.row];
    NSString *text = [status objectForKey:@"text"];
    
    cell.textLabel.text = text;
    
    return cell;
}

描写するセルなどを指定しています。

f:id:tereka:20140225124122p:plain

参考文献

http://qiita.com/paming/items/9a6b51fa56915d1f1d64
http://www.appbank.net/2012/06/30/iphone-news/434166.php
http://ios.rainbowapps.jp/text_dev/10

次回はさすがにユーザー名を表示をしたいのでカスタムセル周りを対策したいと思います。

TwitterViewController

TwitterViewController.h

#import <UIKit/UIKit.h>

@interface TwitterViewController : UITableViewController{
    NSArray *tweets;
}
- (IBAction)TwitterButton:(id)sender;

@end

TwitterViewController.m

#import "TwitterViewController.h"
#import <Social/Social.h>
#import <Accounts/Accounts.h>

@interface TwitterViewController ()

@end

@implementation TwitterViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"TweetCell"];
    //最近、APIが変更になったのでurlは気をつけましょう。
    NSString *apiURL = @"https://api.twitter.com/1.1/statuses/home_timeline.json";
    
    ACAccountStore *store = [[ACAccountStore alloc] init];
    ACAccountType *twitterAccountType =
    [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
    
    [store requestAccessToAccountsWithType:twitterAccountType options:nil completion:^(BOOL granted,NSError *error){
        //Twitterの認証の拒否or認証
        if(!granted){
            NSLog(@"Twitterの認証を拒否");
        }else{
            NSArray *twitterAccounts = [store accountsWithAccountType:twitterAccountType];
            if ([twitterAccounts count] > 0) {
                ACAccount *account = [twitterAccounts objectAtIndex:0];
                NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
                [params setObject:@"1" forKey:@"include_entities"];
                
                NSURL *url = [NSURL URLWithString:apiURL];
                SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter
                                                        requestMethod:SLRequestMethodGET
                                                                  URL:url parameters:params];
                [request setAccount:account];
                [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
                [request performRequestWithHandler:^(NSData *responseData,NSHTTPURLResponse *urlResponse,NSError *error) {
                    if(!responseData){
                        NSLog(@"response error: %@", error);
                    }else{
                        NSError *jsonError;
                        tweets = [NSJSONSerialization JSONObjectWithData:responseData
                                                                 options: NSJSONReadingMutableLeaves error:&jsonError];
                        if(tweets){
                            dispatch_async(dispatch_get_main_queue(), ^{ // 追加
                                [self.tableView reloadData]; // 追加
                            });
                        }else{
                            NSLog(@"%@", error);
                        }
                        //Tweet取得完了に伴い、Table Viewを更新
                    }
                }];
            }
        }
    }];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [tweets count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
    if(cell == nil){ 
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    } 
    
    NSDictionary *status = [tweets objectAtIndex:indexPath.row];
    NSString *text = [status objectForKey:@"text"];
    
    cell.textLabel.text = text;
    
    return cell;
}


- (IBAction)TwitterButton:(id)sender {
    SLComposeViewController *twitterPostVC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
    [twitterPostVC setInitialText:@"てすと"];
    [self presentViewController:twitterPostVC animated:YES completion:nil];
}
@end