2012年4月29日日曜日

非同期仮完了

とりあえず画像の読み込みを非同期にするため、UIImageViewのサブクラスを作ってNSURLConnection使って画像をロードする。@implementationの直下に裸で大域変数置いたらインスタンス同士で書き換えるみたいでエラー出まくりでしかも非同期やからdealloc済みにアクセスしてますよーとか配列にそんなに数入ってないですよーとか毎回違うエラーが出てハマった。ちゃんと@interfaceで宣言しとけば大丈夫みたい。基本か。そうだろうな。

Photo.m
#import "Photo.h"
#define nwf(x) [NSNumber numberWithFloat:x]
#define ofv(x,y) [[x objectAtIndex:y]floatValue]

@implementation Photo

- (id)initWithFrame:(CGRect)frame photourl:(NSMutableArray *)cont;
{
    self = [super initWithFrame:frame];
    if (self) {
  photourl=[[NSArray alloc]initWithArray:cont];
  imgnum=0;
  multiFlg=NO;
  if([photourl count]>1){
   multiFlg=YES;
   imgArr=[[NSMutableArray alloc]initWithCapacity:0];
  }
  UIScreen *uis=[UIScreen mainScreen];
  sw=[uis bounds].size.width,sh=[uis bounds].size.height,sr=sw/sh;
    }
    return self;
}

-(void)loadPhoto{
 [self abort];
 if(!ai) ai=[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
 [ai setCenter:self.center];[self addSubview:ai];[ai startAnimating];
 data=[[NSMutableData alloc]initWithCapacity:0];
 NSURLRequest *req=[NSURLRequest 
        requestWithURL:[NSURL URLWithString:[photourl objectAtIndex:imgnum]]
        cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
 conne=[[NSURLConnection alloc]initWithRequest:req delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
 [data setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)nsdata{
 [data appendData:nsdata];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
 [self abort];
 NSLog(@"error.");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
 if(multiFlg){
  UIImage *img=[UIImage imageWithData:data];
  [imgArr addObject:img];
  [imgArr addObject:nwf(img.size.width)];[imgArr addObject:nwf(img.size.height)];[imgArr addObject:nwf(img.size.width/img.size.height)];
  if([imgArr count]/4<[photourl count]){
   imgnum++;[self loadPhoto];
  }
  else{ //tiling routine
   int curw=0,curh=0,k=0;
   for(int j=0;j<[imgArr count]/4;j++){
    if([[imgArr objectAtIndex:j*4+3]floatValue]<sr&&[imgArr count]/4>j+1){
     int over3=2;
     float firstw=ofv(imgArr, j*4+1),firsth=ofv(imgArr, j*4+2),firstr=firsth/firstw;
     float nextw=ofv(imgArr, (j+1)*4+1),nexth=ofv(imgArr, (j+1)*4+2);
     float newh=firstr*((sw*nexth)/(nextw*firstr+nexth));
     while (sw/newh<sr&&[imgArr count]/4>j+over3) {
      nextw=ofv(imgArr, (j+over3)*4+1),nexth=ofv(imgArr, (j+over3)*4+2);
      newh=(newh/sw)*((sw*nexth)/(nextw*(newh/sw)+nexth));
      over3++;
     }
     j+=1+(over3-2);
     UIGraphicsBeginImageContext(CGSizeMake(sw,curh+newh));
     if(mixedimg){[mixedimg drawAtPoint:CGPointMake(0, 0)];}
     while(k<j+1){
      float neww=newh*[[imgArr objectAtIndex:k*4]size].width/[[imgArr objectAtIndex:k*4]size].height;
      [[imgArr objectAtIndex:k*4]drawInRect:(CGRectMake(curw, curh,neww,newh))];
      curw+=neww;k++;
     }
     curh+=newh;curw=0;
     mixedimg=UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
    }else{
     UIGraphicsBeginImageContext(CGSizeMake(sw,curh+sw*[[imgArr objectAtIndex:j*4]size].height/[[imgArr objectAtIndex:j*4]size].width));
     if(mixedimg){[mixedimg drawAtPoint:CGPointMake(0, 0)];}
     float newh=sw*[[imgArr objectAtIndex:j*4]size].height/[[imgArr objectAtIndex:j*4]size].width;
     [[imgArr objectAtIndex:j*4]drawInRect:(CGRectMake(0, curh, sw, newh))];
     mixedimg=UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     curh+=sw*[[imgArr objectAtIndex:j*4]size].height/[[imgArr objectAtIndex:j*4]size].width;
    }
   }
   [ai removeFromSuperview];
   self.image=mixedimg;
   if(self.image.size.width/self.image.size.height<sw/sh)
    [self setFrame:CGRectMake((sw-sh*self.image.size.width/self.image.size.height)/2, 0, sh*self.image.size.width/self.image.size.height, sh)];
   else [self setFrame:CGRectMake(0, (sh-sw*self.image.size.height/self.image.size.width)/2, sw, sw*self.image.size.height/self.image.size.width)];
   [self abort];
  }
 }
 else{
  [ai removeFromSuperview];
  self.image=[UIImage imageWithData:data];
  if(self.image.size.width/self.image.size.height<sw/sh)
   [self setFrame:CGRectMake((sw-sh*self.image.size.width/self.image.size.height)/2, 0, sh*self.image.size.width/self.image.size.height, sh)];
  else [self setFrame:CGRectMake(0, (sh-sw*self.image.size.height/self.image.size.width)/2, sw, sw*self.image.size.height/self.image.size.width)];
  [self abort];
 }
}

できた。画像のURLが入った配列を引数にして初期化してやればちゃんと読む。複数でも大丈夫。あとはanimatedなgifをどう扱うか。imageIO? UIWebView?ちょっと調べる。

昨日の昼は十六番@長堀橋で十六番ラーメンセット。スープはかなり美味しいが、麺はどうだろう。尾道ラーメンって全部あんな感じなんかな。日清カップヌードル的な、って言ったら怒られるか。でもまた行きたい。
尾道ラーメン 十六番

2012年4月27日金曜日

バージョン管理

仕事が大変でなかなかxcodeで遊べない。
とりあえず画像を非同期取得する前に、バージョン管理の手法を勉強しとく。
このへんを参考?:
Xcode4でアプリのバージョン管理

昨晩は玉造の角力に行ったがなぜか閉まってた。前行った時も閉まってたしやめたんかな。で、急遽日本橋の小洞天へ。ワンタン麺が絶妙な塩分でうまい。今日の昼はまたまた清正で、今月20杯目。

2012年4月26日木曜日

非同期

メソッドの並列処理云々の前に、画像の読み込みを非同期にする必要があるな。
ここらへんを参考に:

[Objective-C][iPhone] 非同期で画像をロードするUIImageView
[iOS SDK]非同期通信で画像をロードする方法について
UIImageをサーバ経由で取得する方法

夜は難波の味仙で担仔麺。おでんみたいなかちかちな煮玉子が入っててなかなか新鮮。程よい辛さでうまかった。

2012年4月25日水曜日

xcode4.3.2

がapp storeからインストールできない。正常終了もできんし、なんか調子悪いなー。
とりあえずdevelopersのサイトからDLしてみる。
それが終わったら並列処理の勉強やな。

夜は麺家 静で中華そば煮玉子にライス。かなりうまい。次はにぼにぼいってみよう。

2012年4月24日火曜日

課題

UIや挙動なんかはなんとなく目処が立った。ちょこちょこ時間かければ完成するだろう。
あとやりたいけどちょっと調べないといけないことを書いとこう。

・GIFはUIWebViewで包む(これは多分やれそう)
・並列処理(パースしながらどうview作るか、view作りながらいつJSONとるか、pvArrをnow起点に前後10posts(?)であふれたやつをどう消すか→nilを代入?)
・JSONの重複回避、since_id算出ルーチン
・bluetoothキーボードでのオペレーション
・大量のfollowee、followerをどう選択させるか(table?)

うーん、結構残ってるな。。。まあ、ひとつひとつ潰していくしか無いな。今まで通り。

並列処理関連は、以下とか参考にしよう:

並列プログラミングガイド
NSOperationQueue スレッドと処理の関係
NSOperation 非並列実行モードと並列実行モードの使い分け

あと、詳解obj-c2.0も。

画面遷移

長押しで逆巻やlikeを出すようにして、デフォルトでは必要最低限のコントローラで遷移させる。ほぼ思惑通りの動きができた。満足。

 ctrlv=[[UIView alloc]initWithFrame:CGRectMake(0, 0, sw, sh)];[self.view addSubview:ctrlv];
 UIImage *nextimg=[UIImage imageNamed:@"next"];UIImage *nextonimg=[UIImage imageNamed:@"next_on"];
 bnext=[UIButton buttonWithType:UIButtonTypeCustom];bnext.alpha=0.7;
 [bnext setImage:nextimg forState:UIControlStateNormal];[bnext setImage:nextonimg forState:UIControlStateHighlighted];
 [bnext setFrame:CGRectMake(sw-nextimg.size.width-10, sh-nextimg.size.height-30, nextimg.size.width,nextimg.size.height)];
 [bnext addTarget:self action:@selector(npost) forControlEvents:UIControlEventTouchUpInside];
 prelong=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(dpl)];
 [bnext addGestureRecognizer:prelong];
 [ctrlv addSubview:bnext];
 UIImage *previmg=[UIImage imageNamed:@"prev"];UIImage *prevonimg=[UIImage imageNamed:@"prev_on"];
 bprev=[UIButton buttonWithType:UIButtonTypeCustom];bprev.alpha=0.7;
 [bprev setImage:previmg forState:UIControlStateNormal];[bprev setImage:prevonimg forState:UIControlStateHighlighted];
 [bprev setFrame:CGRectMake(sw-previmg.size.width-10, sh-previmg.size.height-80, previmg.size.width,previmg.size.height)];
 [bprev addTarget:self action:@selector(ppost) forControlEvents:UIControlEventTouchUpInside];

 UIImage *rblgimg=[UIImage imageNamed:@"reblog"];UIImage *rblgonimg=[UIImage imageNamed:@"reblog_on"];
 brblg=[UIButton buttonWithType:UIButtonTypeCustom];brblg.alpha=0.7;
 [brblg setImage:rblgimg forState:UIControlStateNormal];[brblg setImage:rblgonimg forState:UIControlStateHighlighted];
 [brblg setFrame:CGRectMake(sw-rblgimg.size.width-10-nextimg.size.width-10, sh-rblgimg.size.height-30, rblgimg.size.width,rblgimg.size.height)];
 [brblg addTarget:self action:@selector(rblg) forControlEvents:UIControlEventTouchUpInside];
 rllong=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(chngrl)];
 [brblg addGestureRecognizer:rllong];
 [ctrlv addSubview:brblg];
 UIImage *likeimg=[UIImage imageNamed:@"like"];UIImage *likeonimg=[UIImage imageNamed:@"like_on"];
 blike=[UIButton buttonWithType:UIButtonTypeCustom];blike.alpha=0.7;
 [blike setImage:likeimg forState:UIControlStateNormal];[blike setImage:likeonimg forState:UIControlStateHighlighted];
 [blike setFrame:CGRectMake(sw-likeimg.size.width-10-previmg.size.width-10, sh-likeimg.size.height-30, likeimg.size.width,likeimg.size.height)];
 [blike addTarget:self action:@selector(like) forControlEvents:UIControlEventTouchUpInside];
- (void)npost{
 if([pvlayer viewWithTag:now]==[pvArr lastObject]) return;
 [[pvlayer viewWithTag:now++] removeFromSuperview];
 [pvlayer addSubview:[pvArr objectAtIndex:now-1]];
 [bprev removeFromSuperview];
}
- (void)ppost{
 if(now==1){[bprev removeFromSuperview];return;}
 [[pvlayer viewWithTag:now--] removeFromSuperview];
 [pvlayer addSubview:[pvArr objectAtIndex:now-1]];
 if(now==1)[bprev removeFromSuperview];
}
- (void)dpl{
 if(now!=1) [ctrlv addSubview:bprev];
 else if([bprev isDescendantOfView:ctrlv])[bprev removeFromSuperview];
}
- (void)rblg{
 NSLog(@"reblog.");
}
- (void)like{
 NSLog(@"like.");
}
- (void)chngrl{
 if([brblg isDescendantOfView:ctrlv]){[brblg removeFromSuperview];[ctrlv addSubview:blike];[blike addGestureRecognizer:rllong];}
 else{[blike removeFromSuperview];[ctrlv addSubview:brblg];[brblg addGestureRecognizer:rllong];}
}

できた。でもコードがださいのよねー。素人まるだし。
reblog,likeなどの実装はまだ。でもだいぶ進んだなー。

2012年4月23日月曜日

UI

久々にfireworksをたちあげてインターフェイスの構築。なんとなくイメージは固まってきたかな。macとwindowsの行き来がめんどくさい。
昼は大阪大勝軒@日本橋でつけ麺。並400g中盛800g大盛1500gという量子力学的な麺量設定のため、なかなか中盛に手が出せない。でもうまい。

2012年4月22日日曜日

quote

photoはある程度目処が付いたので、quoteのviewを作成。とりあえずUITextViewを使う。文字が少ないと質素になるので、文字数とフォントサイズを反比例させた。ひねりの効いた短文などはなかなかインパクトがあってよい。

}else if([[typeArr objectAtIndex:i]isEqualToString:@"quote"]){ //quote
 NSString *text=cont;
 text=[text stringByReplacingOccurrencesOfString:@"<br/>" withString:@"\n"];NSRange r;
 while ((r=[text rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location!=NSNotFound)
 text=[text stringByReplacingCharactersInRange:r withString:@""];
 UITextView *tv=[[UITextView alloc]initWithFrame:CGRectMake(10, 20, sw-20, sh-20)];
 tv.text=text;tv.font=[UIFont fontWithName:@"Helvetica" size:[text length]>13?300/[text length]*(3-[text length]/150)+15:75];
 tv.textColor=[UIColor blackColor];tv.backgroundColor=[UIColor clearColor];
 tv.editable=NO;
 [postv addSubview:tv];
}

できた。あとは引用符の画像を付けてみる。

UILabel

松江に出張行ってきた。人生初島根。向こうではisemiya527でもやしラーメン、戻ってきてから鶴橋ののぼり屋で味付玉子入りラーメン。どちらもまずまず。
で、帰ってきてからblog_nameとcaptionの表示部分をちょこちょこ書いてみた。UILabel使ってこんな感じで。

UILabel *bname=[[UILabel alloc]init]; //blog_name
bname.text=[bnameArr objectAtIndex:i];bname.font=[UIFont fontWithName:@"Helvetica" size:10];
bname.textColor=[UIColor blackColor];bname.backgroundColor=[UIColor whiteColor];bname.alpha=0.5;
CGFloat bwidth=[bname.text sizeWithFont:bname.font constrainedToSize:CGSizeMake(sw,10) lineBreakMode:UILineBreakModeTailTruncation].width;
bname.frame=CGRectMake(0,0,bwidth,10);
[postv addSubview:bname];
if([capArr objectAtIndex:i]){ //caption
 NSString *capText=[capArr objectAtIndex:i];NSRange r;
 while ((r=[capText rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch]).location!=NSNotFound)
 capText=[[capText stringByReplacingCharactersInRange:r withString:@""] stringByReplacingOccurrencesOfString:@"\n" withString:@""];
 UILabel *caption=[[UILabel alloc]init];
 caption.numberOfLines=0;
 caption.text=capText;caption.font=[UIFont fontWithName:@"Helvetica" size:10];
 caption.textColor=[UIColor blackColor];caption.backgroundColor=[UIColor whiteColor];caption.alpha=0.5;
 CGSize csize=[caption.text sizeWithFont:caption.font constrainedToSize:CGSizeMake(sw, 30) lineBreakMode:UILineBreakModeTailTruncation];
 caption.frame=CGRectMake(0,sh-csize.height,csize.width,csize.height);
 [postv addSubview:caption];
}

できた。
でもなんか無駄が多い気がする。もうちょいエレガントに書けんもんか。

2012年4月19日木曜日

viewWithTag

というのがあるのか。勉強になるなー。
[Objective-C]viewWithTagメソッドは入れ子になったビューにもアクセスできるみたい

ページ遷移するときremoveFromSuperviewしてからaddSubviewするか、逆でいくか。逆で行く方法で悩んでたけど、これでいけるんかな。あとで試す。

夜はメン太ジスタ@玉造でメン太そばとごはん小。無鉄砲とは大違いの素晴らしい炊き具合の米が塩っ気の多いスープ、味玉に合う。メン太そばの平麺ももうちょい固ければよいがうまい。満足。

大域変数2と無鉄砲

floatとかの変数はそのまま{}の外側に書けば普通に大域変数になるみたい。なーんだ。
とりあえず画像が複数の場合のタイリングを別メソッドにして書きなおした。あっさり動いて拍子抜け。

そんなことより今日は初めて無鉄砲@大国町(大阪本店)に行った。20人以上並んでて店に入るまで30分かかった。だから結構期待してたけど、うん。美味しくない。まずごはんはべちゃべちゃ。スープも、知らんかったとはいえ、普通の濃さであれはないよ。22杯/monthでラーメン食べてるから言わせてもらうけど、あれに並ぶ意味が分からん。自分的に食事を残すのは人生でやっちゃいけないことの上位に入るので(同じようなことを佐藤雅彦先生も書いていたが)、途中まで頑張ったけど、残した。あれで満腹になるのは人生損する気がした。普通に小十郎行っときゃよかった。

2012年4月16日月曜日

tiling routine

縦横比の異なる複数の画像を、なるべく効率的に隙間なく並べる、というか最終的にはアスペクト比を維持したまま画面からはみ出さないようリサイズするので、複数の画像を矩形に組み上げるルーチン、かな。をとりあえず動くようにしてみた。NSNumberが直接演算できないとか、配列の添字がobjectAtIndex:ってのに未だに慣れず、コードを綺麗に書けない。マクロもどうかなーってくらいの微妙な冗長さ。どうするのがいいのかな。

配列contArrにはtumblrAPIから返ってきたresponse.postsの中身が入ってるという前提で、以下のとおり:

1.photoの場合はtumblrAPIからoriginal_sizeのurlが配列で返ってくるので、高速列挙にぶちこんでサイズ、比率、自身のUIImageオブジェクトを配列に格納する。1postに画像が複数ある場合は当然複数入る。
2.画像を取り出して、画面の縦横比よりも縦長で且つまだ次の画像があれば、その二つが隙間なく画面の幅に収まるよう横に並べられる共通の高さを取得(newh)する。
3.それでもまだ画面の縦横比より縦長で且つまだ次の画像があれば、先のものと合わせて隙間なく画面の幅に収まるよう横に並べられる共通の高さを取得(newh)する。これは全部の画像をくっつけて縦長じゃなくなるまで続ける。”縦長”の定義は、画面の比率以外にも、”正方形より”縦長、”横2:縦1より”縦長などが考えられるが、現時点では画面比で。
4.既に同じように生成した画像があれば(配列に画像を残して横長になった場合は)、まずその画像をdrawAtPointしておく。
5.2~3で処理した画像をdrawInRectする。
6.複数画像を1つの画像に合体(getImage)する。
7.1postに画像が1つ、または画像が横長、または縦長でも配列最後の画像であれば、単に画面幅に合わせてリサイズし、既に同じように生成した画像があれば(配列に画像を残して横長になった場合は)、まずその画像をdrawAtPointしてからdrawInRectしてgetImageする。
8.最後に1post分の画像としてUIImageViewに貼ってアスペクト比を維持したまま画面からはみ出さないようリサイズ。

#define nwf(x) [NSNumber numberWithFloat:x]

- (void)makeTimeLine{
 UIScreen *uis=[UIScreen mainScreen];
 float sw=[uis bounds].size.width,sh=[uis bounds].size.height,sr=sw/sh;
 int i=0;
 for(id cont in contArr){
  if([cont isKindOfClass:[NSArray class]]){
   UIImage *mixedimg;
   NSMutableArray
   *imgSizeArr=[[NSMutableArray alloc]initWithCapacity:0],*imgRatioArr=[[NSMutableArray alloc]initWithCapacity:0],
   *imgSetArr=[[NSMutableArray alloc]initWithCapacity:0];
   for(id parts in cont){ //1.高速列挙にぶちこむ
    UIImage *img=[[UIImage alloc]initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:parts]]];
    [imgSizeArr addObject:nwf(img.size.width)];[imgSizeArr addObject:nwf(img.size.height)];
    [imgRatioArr addObject:nwf(img.size.width/img.size.height)];
    [imgSetArr addObject:img];
   }
   int curw=0,curh=0,k=0;
   for(int j=0;j<[imgSetArr count];j++){
    if([[imgRatioArr objectAtIndex:j]floatValue]<sr&&[imgSetArr count]>j+1){ //2.画像の比率チェック
     int over3=4;
     float firstw=[[imgSizeArr objectAtIndex:j*2]floatValue],firsth=[[imgSizeArr objectAtIndex:j*2+1]floatValue],firstr=firsth/firstw;
     float nextw=[[imgSizeArr objectAtIndex:j*2+2]floatValue],nexth=[[imgSizeArr objectAtIndex:j*2+3]floatValue];
     float newh=firstr*((sw*nexth)/(nextw*firstr+nexth));
     while (sw/newh<sr&&[imgSetArr count]>j+over3/2) { //3.縦長の限りずっと
      nextw=[[imgSizeArr objectAtIndex:j*2+over3]floatValue],nexth=[[imgSizeArr objectAtIndex:j*2+over3+1]floatValue];
      newh=(newh/sw)*((sw*nexth)/(nextw*(newh/sw)+nexth));
      over3+=2;
     }
     j+=1+(over3/2-2);
     UIGraphicsBeginImageContext(CGSizeMake(sw,curh+newh));
     if(mixedimg){[mixedimg drawAtPoint:CGPointMake(0, 0)];} //4.既に合体画像がある場合
     while(k>j+1){ //5.複数画像を描画
      float neww=newh*[[imgSetArr objectAtIndex:k]size].width/[[imgSetArr objectAtIndex:k]size].height;
      [[imgSetArr objectAtIndex:k]drawInRect:(CGRectMake(curw, curh,neww,newh))];
      curw+=neww;k++;
     }
     curh+=newh;curw=0;
     mixedimg=UIGraphicsGetImageFromCurrentImageContext(); //6.複数画像を1つの画像に
     UIGraphicsEndImageContext();
     }else{ //7.画像が1つの場合は単に画面幅に合わせてリサイズ
      UIGraphicsBeginImageContext(CGSizeMake(sw,curh+sw*[[imgSetArr objectAtIndex:j]size].height/[[imgSetArr objectAtIndex:j]size].width));
      if(mixedimg){[mixedimg drawAtPoint:CGPointMake(0, 0)];}
      float newh=sw*[[imgSetArr objectAtIndex:j]size].height/[[imgSetArr objectAtIndex:j]size].width;
      [[imgSetArr objectAtIndex:j]drawInRect:(CGRectMake(0, curh, sw, newh))];
      mixedimg=UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      curh+=sw*[[imgSetArr objectAtIndex:j]size].height/[[imgSetArr objectAtIndex:j]size].width;
     }
    }
   UIImageView *imgset=[[UIImageView alloc]initWithImage:mixedimg]; //8.1post分の画像を生成
   if(mixedimg.size.width/mixedimg.size.height<sw/sh) [imgset setFrame:CGRectMake(0, 0, sh*mixedimg.size.width/mixedimg.size.height, sh)];
   else [imgset setFrame:CGRectMake(0, 0, sw, sw*mixedimg.size.height/mixedimg.size.width)];
   [self.view addSubview:imgset];
   }else{//NON-photo
    NSLog(@"%d / %@",i,cont);
   }
  i++;
 }
}

できた。
横に並べる場合の比率なんかはこれからテストする。
というか、複数画像の場合は別メソッドに抜き出して渡したほうがいいな。あとでやろう。

昨晩は日本橋の一蘭。うまく隙間時間に入れて待たずに食べれた。帰るときは結構な行列だった。今月10杯目。ペースが遅い。

2012年4月14日土曜日

マクロ

なるほどー、こうやるんだねー。読んだ読んだ。どっかで。確かに。

Initialize NSArray with floats?
iPhoneデバッグ用のマクロで、クラス名とメソッド名を自動的にログ出力する

obj-cの場合、こういうのちゃんと使わないとめちゃくちゃ見難いコードになるもんな。

2012年4月13日金曜日

いや、違うな

横の個数maxを平方根にすると極端な場合に対応できない。横に並べた場合に画面比より縦長な限り横に並べ続けることにする。
1個目が画面比より横長なら画面幅に合わせてリサイズ、縦長なら2個目取り出してAh/(Aw+Ah/Bh*bw)<1.5なら横並べルーチン走らせて最初に戻り、>1.5なら3個目取り出してAh/(Aw+(Ah/Bh*bw)+(Ah/Ch*Cw))<1.5 or >1.5で同じように処理して、と延々と繰り返せば効率的に隙間なく並ぶ、かも。

そろそろ

photoが複数の場合のタイリングルールもなんとなくまとまってきた。
画像の個数の平方根(小数点切上)を横に並べるmaxとして、最初の画像のアスペクト比が全画面の比率より横長の場合は問答無用で全画面の幅に合わせてリサイズした画像を返し、縦長の場合はその画像と次の画像(max以内であればその次もその次も...)のアスペクト比との平均も出して、全画面の比率より横長になる(くらい極端な横長画像が含まれてる)場合はそれまでに出てきた画像は問答無用で全画面の幅に合わせてリサイズして返し、縦長の場合は横に敷き詰めるルーチンを走らせて並んだ状態で画像を返す。返ってきた画像を下へ下へくっつけていくのを配列の0~lastまでやれば、うまく並ぶんじゃないだろうか。自分以外にはほとんど訳の解らん文章だろうが、とりあえずこれで試してみる。

で、これをベースにuiviewを生成してみる。以下など参考に:

画像処理に使えるUIImageのTips10個
UIImage のリサイズ
複数のUIImageオブジェクトから1つのUIImageオブジェクトを作る

2012年4月12日木曜日

縦横比の違う画像を隙間なく横に敷き詰める

にはどうするかで悩む。(TumblrAPIのJSONから帰ってきたphotoが複数の場合があるので)
縦に敷き詰めるには横幅をwindowのwidthいっぱいに変形して下に並べていけば済むが、横にする場合は隙間が出ないように考えないと行けない。
適当に連立方程式を解いてみた。
windowのwidthをW、画像Aの横縦をAw,Ah、以下Bw,Bh,Cw,Ch ... Lw,Lh(LastImage)とした場合:

(Ah/Aw) * ((W*Lh) / ((Lw*(Ah/Aw)+Lh) + ((Ah/Aw)/(Bh/Bw)*Lh) + ((Ah/Aw)/(Ch/Cw)*Lh) ...))

を全画像の高さとしてそれぞれリサイズすればぴったりとwindowの横幅いっぱいに敷き詰めてなおかつ隙間が出ない。はず。

夜はばっこ志@十三でとんこつに煮玉子。うまい。

2012年4月10日火曜日

/posts

はoffsetの上限がないみたい!1200までは試してみたが普通に動いてる。よかった…。とりあえずGETATokenクラスで初回AccessTokenとsecretとったあとはnotificationして自分を殺してMAKETimeLineクラスのインスタンス置いてdashboardかblogかの引数渡してjson受け取るところまではきた。順調。そろそろview組むか。またいろんな壁にぶち当たるだろうが頑張る。夜は味壱でチャーシューメン並ネギゆで玉子おにぎり。

着々

とりあえずrootのviewcontrollerではuserdefaultsにaccesstokenとsecretがあるかだけチェックし、無ければ取得するためのクラス、あればdashboardを読むためのクラスからインスタンス作ってaddsubviewするようにさらに細分化した。特に何の問題もなくできた。だいぶ成長したかな。

2012年4月9日月曜日

UIViewController

の中でさらにUIViewControllerをインスタンス化しても表示されないのに悩む。
addsubviewするときはcontroller.viewでやるのか。わかれば当たり前のことばかりで悔しい。
これで初回だけaccessTokenをとるフローを別のクラスに分けられた。

2012年4月8日日曜日

offset&since_id in Tumblr API

について調査。とりあえずこんな感じで。

NSMutableArray *prmt=[NSMutableArray arrayWithObject:[[OARequestParameter alloc]initWithName:@"limit" value:@"20"]];
[prmt addObject:[[OARequestParameter alloc]initWithName:@"offset" value:@"250"]];
[prmt addObject:[[OARequestParameter alloc]initWithName:@"since_id" value:@"xxxxxxxxxxx"]];
[request setParameters:prmt];

since_idをセットするとそこから新しい方に向かってoffsetが機能する、のか?
offset=250にして270番目のpostより適当に予測した古いidをsince_idにすると最新に近いポストのセットが返され、同じsince_idでoffset=0にすると予想してた(270+α番目のポストから新しい方に向かって、つまり250-270より古いセットが返される)挙動になる。
250までは何も考えずにoffset+=20し続けて(タイムラグによるpostの重複防ぐ工夫はいるが)250以降はoffset使わずに20個古いsince_idの予測によるdashboard取得、ということになるか。やってみる。

大域変数

複数メソッドから参照させるNSMutableArrayを用意したけど警告でまくりで悩んだ。@propertyして@synthesizeしてloadViewの中でself.GLOBALarray=[NSMutableArray alloc]init]するのか。loadViewの中でNSMutableArray *GLOBALarray=[]でやってた。またひとつ賢くなった。

2012年4月7日土曜日

二杯

今日は半ドンで住道の若松へ。期待していた程ではなかったので、尼崎の大貫本店へ。まさかのラーメン屋はしご。こっちはなかなかいけた。
TumblrのauthorizeURLが死んでたみたいなのでメールしたら「ドキュメント読んでライセンス読んでGoogleGroupで既存の問題じゃないか確認してなかったらフォーラムにポストしてそれでも無理なら連絡よこせ」って帰ってきた。まー一日経ったらURL生き返ってたからいいけど。
で、dashboardはやはりoffsetの上限が250みたい。
/user/dashboard ignores offset > 250?
どうやらsince_idはolder thanじゃなくてnewer than らしく、270(offset250+limit20)番目のpostIDからちょうどイイ感じに若いpostIDを推定してそこから20件吸い出してまたちょうどイイIDを推定してのエンドレスロジックを考えないといかんようだ。不便。

2012年4月5日木曜日

タイル

とりあえず一発目にとったdshbrdの写真をタイル状に並べた。
やたら無駄が多い気がするが、まずはよしとしよう。
- (void)apiTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data{
 NSDictionary *bd=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
 for (int i=0; i<20; i++) {
  NSString *urlstr=[[[bd valueForKeyPath:@"response.posts.photos.original_size.url"]objectAtIndex:i]objectAtIndex:0];
  UIImage *img=[[UIImage alloc]initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlstr]]];
  UIImageView *imgv=[[UIImageView alloc]initWithImage:img];
  [imgv setFrame:CGRectMake((i%4)*80, i/4*80, 80, 80)];
  [self.view addSubview:imgv];
 }
}

2012年4月4日水曜日

ARC

今日は息子の入園式で振休。
oauthconsumerをARCにコンバートしたものを見つけたので、プロジェクトをARC対応で作り替えてみる。
以下手順:

1.https://github.com/jimkang/oauthconsumer からDL
2.TARGETS>Build Phases>LinkBinaryWithLibrariesからSecurityFrameworkとlibxml2.dylibを追加
3.TARGETS>Build Settings>SearchPaths>HeaderSearchPathのDebugとRelease両方に$SDKROOT/usr/include/libxml2を追加
4.TARGETS>Build Settings>Apple LLVM compiler 3.0 -warnings の Missing Function PrototypesをNoに
5.performSelectorのエラーが何個も出るので以下のように回避
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[delegate performSelector:didFinishSelector withObject:ticket withObject:responseData];
#pragma clang diagnostic pop
6.OATokenクラスのinitWith系のメソッドにverifierの引数が無いので追加
7.tumblrがsecretをnullで返すのでその場合は値を上書かないようinitWithKeyを修正(if(aSecret) self.secret = aSecret;)

できた。