FQLで友達の写真からコメントを取得する方法
今日はあんまりコードを書かなかったから、全然ネタがなーい!!
モックプランコンテストのキックオフも行って、企画の考え方ってむっずいーなって思った。
ただ、企画を毎日のように考えるのはすごく楽しいだろうし、早くそれを実現する力が欲しい…。
話はずれましたが、FQLでphotoのcommentを撮る方法についてです。
photoのcommentを取得する方法としまして、ここに書いてある通り
SELECT username,text FROM comment WHERE object_id IN (SELECT object_id FROM photo WHERE aid="20531316728_324257")
でとれるはずだったんですが、なぜかphotoテーブル側のobject_idがStringとint型の二つで返ってきてて、つまってました。
今日行なったらなぜか(危険)ちゃんとint型に直ってて、簡単にできました。
usernameについては取得出来なかったんで、調査しておきます。
そしてこのまま友達たちがアップした写真の更新順で上位50番目からの写真のコメントを取り出すと…(長
SELECT username,text FROM comment WHERE object_id IN (SELECT object_id FROM photo WHERE aid IN (SELECT aid FROM album WHERE owner IN (SELECT uid2 FROM friend WHERE uid1 = me() ) ORDER BY modified DESC ) ORDER BY modified DESC LIMIT 50)
と、ちょっと長いですが取得出来ます。
写真と同時に取得出来ないのが痛いため、写真を取得する際にobject_idを保存しておき、適宜コメントを取り出すのがいいと思います。
サンプルコードを読む〜LazyTable編〜
今日はいつもよりまとめられてません!!
ただこのブログは毎日の活動を記すという裏設定もあるため、頑張ります.
前回UITableViewCellの非同期についてまとめましたが、なんと、そんなの無駄になるくらいな出来事が起きました。
Appleが提供しているサンプルコードがたくさんありました。
これもブログ書いたおかげで知れたという事で…(ポジティブ)
今回は非同期で画像をロードしているサンプルコード「LazyTable」について。
がっつりサンプルコードを読んだ訳じゃないので触り程度で。
【LazyTableAppDelegate.m/h】
毎回あるAppDelegateと一緒。非同期で画像データをxmlで取得している。
xmlの処理を別スレッドで【ParseOperation.m/h】に処理を任せている。
【AppRecord.m/h】
ダウンロードデータしたするアイコンとかなんか色々なデータを保持するクラス。
データ群は別にしておくと便利そう。これをView同士で共通のインスタンスで使えば値保持できるのかな。
奇麗にコード書くヒントになりそうな予感!
【IconDownloader.m/h】
ここでアイコンのダウンロードを行なう。
【RootViewController.m/h】
メインのクラス。ここでTableViewを使ってアイコンや名前などを表示している。
ドラッグ中、スクロールが止まらないとダウンロードは開始されない。
indexPathをキー、IconDownloaderクラスのインスタンスを値にしてダウンロードしている物を識別。
また、アイコンがダウンロードされていない場合はダウンロードするという処理付き。
流石サンプルコード。初心者にも読み易い!!
いくつかまだ理解出来てないのはあるけど、データを別のクラスで保持しておくのとか便利そう。
そういう場合はどうするんだろ、デリゲートで保持が無難?
UITableViewCellで画像を非同期でロードしようとしたときに困った事②
今回は少し自分のまとめをするためにも書きます。(今日はですます口調の気分)
以前GCDを用いた非同期について書きましたが、やめました。
簡単に別スレッドを作れてとても楽だったんですが、自分が非同期するのって今の所URLから何かダウンロードする時くらいだったので、複雑にするよりも少しシンプルに行きたいと思います。以前も書いたんですが、UITableViewCellでのNSURLConnectionを使った非同期についてです。
あの後少し意見を貰い(やっぱり書くっていいですね、たまに誰かから意見頂ける)、NSMutableDictionaryでindexPathをキーにして色々保存することがUITableViewCellを制覇するコツでした。ただ、やっぱり再利用の問題は解決出来ませんでした。
例えば、各セクションの0行目のセルにだけ画像をつけたい場合
if([picFriendsPhotos_ objectForKey:indexPath]) {
cell.textLabel.text =@"";
cell.imageView.image = [picFriendsPhotos_ objectForKey:indexPath];
return cell;
}
見たいに書きます。しかし、imageは特定のセルにしか貼付けてないはずが、他の行目のセルに見えたりしてしまいます…。苦肉の策として、それ以外のセルにはnullを貼付けることでどうにか防いでます。(今の所不便は無い…今の所…)
NSURLConnectionを使った非同期については、
① NSURLRequest *req = [NSURLRequest
requestWithURL:[NSURL URLWithString:src]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
NSLog(@"%@",src);
conn_ = [[NSURLConnectionalloc] initWithRequest:req delegate:self]; //非同期開始
if(conn_) {
receiveData_ = [[NSMutableDataalloc]initWithCapacity:0];
② NSString *str = [NSString stringWithFormat:@"%d%", conn_];;
③ [conInfo_ setValue:indexPath forKey:str];
④ [conType_ setValue:@"photo" forKey:str];
NSLog(@"yescomeon getimage");
maxCountPhoto++;
}
①でとその下らへんで非同期を開始します。
そして、自分的にはこれが一番いいと思ってるんですが、②でcoonectionをNSStringにしてしまい、③でindexPathを登録、④で今回ダウンロードする種類を指定するのがいいんではないかと思います。ここらへんは他の人のあんまり参考にしなかったんで、良いのか悪いのかわかりません!誰か教えて頂けると喜んじゃいます。
後は- (void)connectionDidFinishLoading:(NSURLConnection *)connectionメソッド内で
if ([[conType_ objectForKey:str] isEqual:@"icon"]) {
UIImage *me = [UIImage imageWithData:receiveData_];
[picFriendsOwnerPhoto_setValue:me forKey:[conInfo_objectForKey:str]];
NSLog(@"type icon");
[self.tableView reloadData];
}
elseif ([[conType_objectForKey:str] isEqual:@"photo")・・・・
connectinoのタイプ分け、そしてconnectionについてるindexPathをキーにしてデータの紐付けを行なえばバッチグーだと思います。
tableViewのreloadDataメソッドを呼べば勝手に更新されてきます。
indexPathについては前々回の記事より
①NSUInteger newIndex[] = {0, 1}; // 0番目のセクションの2行目
②NSIndexPath *newPath = [[NSIndexPath alloc] initWithIndexes:newIndex length:2];
とかけば、指定出来ます。後々後、これは自分の勝手な考えなんですが(そんな事言ったら全部そうだけど)、-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPathメソッド内では、基本URLConnectionやら他の無駄な処理はあんまりさせない方がいいと感じました。だって、わかりづらいし、ごちゃごちゃしてる。割り切って、tableの中身を表示するだけ。でなるべく考えた方がいいと思います。そして、なんで文字が大きくならないんだー!!!はてブロー!俺が悪いのかー!
今週面白いと思った記事
日曜日までに面白い記事がたまってたらいくつか紹介しようかなということで、技術的な記事も混ぜながら自分が「面白い!」や「ちょっと言いたい事が…」と思った記事を載せまーす!
場所にフォーカスして、スレッドをたてるサービス「geo talking」
今週じゃないですこれ…。前の保管してた記事見たら、なんか面白そうなのあったんで!
です。スレッドがその場で立てれるなんて面白い!と思って少し利用してたんだけど、人が少ないのとスマフォのアプリ出てくれたら使い易いのになぁって感じた。
錯覚って不思議!面白い!リアルなのになんかSFチックでいい。
(1)のほうも合わせて読んでほしい。ゲームフィケーションを利用する上で、基礎となる考え方の順番みたいな事を書いてある記事。ゲームしかまだまだ思い浮かばないけど、最近ではプログラミングの学習系のサイトやらではよく見られると思う。なんか他に使えないかなー・・・トイレに取り入れたい。
[CSS]永遠にスクロールしていたくなる、気持ちいいエフェクト -CSS Scroll Effects
きもちい。iPhoneでこれ適応したいなぁ、webじゃなくてネイティブで実装してみたい。
賢い! 丸テーブルにも四角テーブルにもなる自由自在な机(動画あり)
ぐっど。これ系いい!Pinterestかどっかのデザインサイトにも組み立て可能なベッドやらソファーやらあったんだけどどこだろ…探しておきます。
スクロールすると左右から画像が集まってくるWebデザインのNizoっぽいやつをjQueryで作る
ヒュージョンしか思いつかないw
自分の今年の目標に付け足した物として、デザイン力を高めるってのを入れた。それは、この記事にも書いてある通りで、便利なアプリとかでもデザインがないとなんか寂しく、インパクトに欠ける。欲張り過ぎかもしれないけど、エンジニアもデザイン力をつけたほうがいいよね。
ゲーム大手 Valve 、ウェアラブルコンピュータの研究開発に着手。求人中。
ウェアラブルと言ったら、センサー系の研究に自分を一気に引き込んでくれた寺田努さんが思いついた。論文の紹介とかしてもいいのかわかんないんで、是非寺田さんの論文読んでほしい!
エンジニアのためのポートフォリオ作成サービスhat.ioが登場
そういえば、エンジニアって就活の時ポートフォリオってないよね。自分はたまたまあるイベントに参加したから作ってたけど…すぐ人事の方に見せれるし、見せれば話し易くて受けもいいから作るべき!
GCDを用いた非同期
そのうちGitにあげます!上げれるほど奇麗じゃないからも・・もう少し…!
以前の記事でUITableViewCellで画像を非同期ロードしようとした際に奇麗に表示出来なかった。
そもそもindexPathというものを理解していなくて、indexPathはsectionとcellで出来てるらしい。
①NSUInteger newIndex[] = {0, 1}; // 0番目のセクションの2行目
②NSIndexPath *newPath = [[NSIndexPath alloc] initWithIndexes:newIndex length:2];
こんな風に書く事で①でセクションの番号(indexPath.section)、cellの行数(indexPath.row)からindexPathを作り出す配列を作り、②でNSIndexPathを作る。lengthについては①の配列が2つのため2(つまり毎回2?)。
そしてNSMutableDictionaryにnewPathをkeyにしてUIImageとか画像のURLを紐づけておけばいい。
こんな感じ [self.picFriendsPhotossetObject:picforKey:newPath];
本題に入るけど、GCDを使った非同期。
まずはパクリが大切なんで…
9割9分9厘くらいこの方のを参考にしました。僕の見る必要ないです(ぁ。
http://d.hatena.ne.jp/yuum3/20101216/1292490323
ただ、このやり方だとfqlを叩いたあとに返り値が来る前に
dispatch_async(timeline_queue, ^{
[selfgetPublicTimeline];
dispatch_async(main_queue, ^{
[self.tableView reloadData];
});
});
ここのgetPublicTimeLineの処理が終わってしまう。
そこで、まずgetPublicTimeLineメソッド内で無限ループを作っておく。
while(!flag) {}
そして、fqlを叩くと
- (void)request:(FBRequest *)request didLoad:(id)result;データが返ってくるんだけど
そのメソッド内で flag = YES; とやって!!!
そしたらgetPublic内でfalg=YESの場合の処理をすればいい!!
このやり方はクールじゃないから、早く違う方法見つける予定…。
cell内の画像の表示については
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPathメソッド内で
if([picFriendsPhotos_ objectForKey:indexPath]) {
① cell.imageView.image = [picFriendsPhotos_ objectForKey:indexPath];
cell.textLabel.text = nil;
}
② cell.imageView.image = [picFriendsPhotos_ objectForKey:indexPath];
とやればとりあえず出来る。しかし問題解決出来てない、出来てない!
セルは1セクションに対して2つしかない。
①で1行目に画像を設置(これは大丈夫)
②でも設置…この②を書かないと2行目のセルにたまに1行目の画像が表示されてしまう!(セルの再利用問題?!)
あれ…書いてて気づいたけど①いりません。やった!今日唯一の成果だ!
うーん、URLのダウンロード非同期にしないと結局遅い。それやろう!!
objective-cのfacebookSDKで友達の写真を取得する方法②
前回の記事で書いた続き。
前回はfqlを使ってfacebookから友達の最新の写真を取得する方法を行なったため、今回はその取得した写真をtableViewCellに同期で表示する方法について。非同期についてはまた次回の方がいいかなぁ。
まず、取得されるデータは
- (void)request:(FBRequest *)request didLoad:(id)result;
に入る。写真の順番は最新の降順で来るため、tableViewCellを上から順番に入れて行けば良い。また、セクション数:50、セル数:2で行なった。
先ほどのメソッドに
self.picFriendsPhotos = [[NSMutableDictionaryalloc]init];
int count = 0;
id result = result_data_;
for (int i = 0; i < [result count] - 5; i++) {
//resultのsrc(URL)からimageを取得する
pic = [UIImageimageWithData:[NSDatadataWithContentsOfURL:
[NSURLURLWithString:[[result objectAtIndex:count] objectForKey:@"src"]]]];
NSUInteger newIndex[] = {count, 0}; // count番目のセクションの1行目
//各indexpathを作成
NSIndexPath *newPath = [[NSIndexPath alloc] initWithIndexes:newIndex length:2];
NSLog(@"indexPath : %@ , count : %d",newPath,count);
//pathをキーに取得したimageを保存
[self.picFriendsPhotos setObject:pic forKey:newPath];
count++;
}
と書く。
resultのデータが50個くるため、それをfor分で回して、各セクションの1行目のセルからNSIndexPathを作成し、それをキーにして取得したimageをセットする。そしたら、
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath内のメソッドで
if([picFriendsPhotos_ objectForKey:indexPath]) {
cell.imageView.image = [picFriendsPhotos_ objectForKey:indexPath];
}
とやると表示される。これだと画像データを取得中は固まってしまう。画像の大きさは130x130?あたりなのでcellの大きさは変えておくと良い。
次回はGCDを用いた非同期について書きます!
objective-cのfacebookSDKで友達の写真を取得する方法
ですます口調かいつも通りの話し方がいいのか毎回迷う僕です。
objective-cのfacebookSDKを使ってみた。
友達の中で最新の写真をフィードっぽく流す…ってのをやりたかったんで、それについてやってみた。
ほとんどHackbookのdemoを参考にしてるんで、参考にするといいかも。(色々すっ飛ばします)
初めはこんな風に自分の情報をまずとっていた[facebook requestWithGraphPath:@"me" andDelegate:self];
これだと@以降に色々設定するのめんどいなーとか思ってた。
そしたらFQLと言われるsql構文を使ってデータを引き出す方法があるなんて…
mysqlとか使った事が有る人にとっては喜ばしいことです。ほんとに。
さきほどのソースコードは
NSMutableDictionary * params =
[NSMutableDictionarydictionaryWithObjectsAndKeys:
@"SELECT uid,name,pic FROM user WHERE uid=me()",
@"query",nil];
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[facebook requestWithMethodName:@"fql.query"
andParams:params
andHttpMethod:@"GET"
andDelegate:self];
こんな風に表す事が出来る。
さっそく友達たちの写真を取得して時系列に表示しようと思った所…
http://saruzaurus.blogspot.jp/2009/06/facebook-fql.html
この方の記事にも書いてある通り、WHEREを記述する必要が有り、ちょっと厄介そう…。
まず友達のIDを取得する必要がある。ここにかいてある通り
SELECT uid2 FROM friend WHERE uid1 = me() で友達のidを取得出来る。
次は友達のアルバムを取得するために
SELECT aid FROM album WHERE owner = uid2 をする必要が有る。
この時 SELECT aid FROM album WHERE owner IN (SELECT uid2 FROM friend WHERE uid1 = me()) を行なう事で、すべての友達のすべてのアルバムを取得する事が出来る。ただ、最新の情報ぐらいでいいかなぁと思い、まずは
SELECT aid FROM album WHERE owner IN (SELECT uid2 FROM friend WHERE uid1 = me()) ORDER BY modified DESC;
とする。ORDER BY modified DESC は変更した日付を降順で表示するって意味。
そして、そこから写真を取り出すには
SELECT src FROM photo WHERE aid= を行なう必要が有る。
先ほどの友達のアルバムのidを取得する奴と合わせて…
SELECT src FROM photo WHERE aid IN (SELECT aid FROM album WHERE owner IN (SELECT uid2 FROM friend WHERE uid1 = me()) ORDER BY modified DESC)とする。そしてさらにさらにまたmodifiedでソートして、とりあえず50枚とれればいいから…
SELECT src FROM photo WHERE aid IN (SELECT aid FROM album WHERE owner IN (SELECT uid2 FROM friend WHERE uid1 = me()) ORDER BY modified DESC) ORDER BY modified DESC LIMIT 50;
で出来上がり!!なんか長過ぎ、怪しすぎ…。
こんな感じで友達達の写真の最新情報を取得が出来た…はず!!!
あ、permissionの変更も忘れずに!
NSArray *permissions = [[NSArrayarrayWithObjects:@"user_about_me",@"publish_stream",@"user_photos",@"friends_about_me",@"friends_photos", nil]retain];